blob: 67b852a6ed1a3abda9e391be57ab31aa30c1f515 [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 Jeanneret1359c732019-08-01 21:40:02 -040022 "encoding/hex"
cuilin20187b2a8c32019-03-26 19:52:28 -070023 "fmt"
24 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040025 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070026 "strconv"
27 "strings"
28 "sync"
29 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053030
Chaitrashree G Sb2b62dd2019-07-24 21:47:04 -040031 "google.golang.org/grpc/codes"
32
Matteo Scandolo945e4012019-12-12 14:16:11 -080033 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070034 "github.com/gogo/protobuf/proto"
35 "github.com/golang/protobuf/ptypes"
Esin Karamanccb714b2019-11-29 15:02:06 +000036 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
37 "github.com/opencord/voltha-lib-go/v3/pkg/log"
38 "github.com/opencord/voltha-lib-go/v3/pkg/pmmetrics"
Thomas Lee S94109f12020-03-03 16:39:29 +053039 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080040 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000041 "github.com/opencord/voltha-protos/v3/go/common"
42 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
43 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
44 oop "github.com/opencord/voltha-protos/v3/go/openolt"
45 "github.com/opencord/voltha-protos/v3/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070046 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040047 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053048)
49
salmansiddiqui7ac62132019-08-22 03:58:50 +000050// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040051const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000052 MaxRetry = 10
53 MaxTimeOutInMs = 500
Manikkaraj kb1d51442019-07-23 10:41:02 -040054)
55
Phaneendra Manda4c62c802019-03-06 21:37:49 +053056//DeviceHandler will interact with the OLT device.
57type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070058 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070059 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040060 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070061 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053062 coreProxy adapterif.CoreProxy
63 AdapterProxy adapterif.AdapterProxy
64 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070065 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070066 exitChannel chan int
67 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053068 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070069 transitionMap *TransitionMap
70 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053071 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040072 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053073 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053074
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +053075 discOnus sync.Map
76 onus sync.Map
77 portStats *OpenOltStatisticsMgr
78 metrics *pmmetrics.PmMetrics
79 stopCollector chan bool
80 stopHeartbeatCheck chan bool
Chaitrashree G Sef088112020-02-03 21:39:27 -050081 activePorts sync.Map
Mahir Gunyela3f9add2019-06-06 15:13:19 -070082}
83
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070084//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070085type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070086 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070087 deviceType string
88 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089 onuID uint32
90 intfID uint32
91 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +000092 uniPorts map[uint32]struct{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -070093}
94
Naga Manjunath7615e552019-10-11 22:35:47 +053095var pmNames = []string{
96 "rx_bytes",
97 "rx_packets",
98 "rx_mcast_packets",
99 "rx_bcast_packets",
100 "tx_bytes",
101 "tx_packets",
102 "tx_mcast_packets",
103 "tx_bcast_packets",
104}
105
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700106//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700107func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700108 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700109 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700110 device.deviceType = deviceTp
111 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 device.onuID = onuID
113 device.intfID = intfID
114 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000115 device.uniPorts = make(map[uint32]struct{})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700116 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530117}
118
119//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530120func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700121 var dh DeviceHandler
122 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400123 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400124 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700125 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700126 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700127 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400128 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700129 dh.device = cloned
130 dh.openOLT = adapter
131 dh.exitChannel = make(chan int, 1)
132 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530133 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530134 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530135 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 -0500136 dh.activePorts = sync.Map{}
cuilin20187b2a8c32019-03-26 19:52:28 -0700137 //TODO initialize the support classes.
138 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530139}
140
141// start save the device to the data model
142func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700143 dh.lockDevice.Lock()
144 defer dh.lockDevice.Unlock()
145 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
146 // Add the initial device to the local model
147 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530148}
149
150// stop stops the device dh. Not much to do for now
151func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700152 dh.lockDevice.Lock()
153 defer dh.lockDevice.Unlock()
154 log.Debug("stopping-device-agent")
155 dh.exitChannel <- 1
156 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530157}
158
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400159func macifyIP(ip net.IP) string {
160 if len(ip) > 0 {
161 oct1 := strconv.FormatInt(int64(ip[12]), 16)
162 oct2 := strconv.FormatInt(int64(ip[13]), 16)
163 oct3 := strconv.FormatInt(int64(ip[14]), 16)
164 oct4 := strconv.FormatInt(int64(ip[15]), 16)
165 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
166 }
167 return ""
168}
169
170func generateMacFromHost(host string) (string, error) {
171 var genmac string
172 var addr net.IP
173 var ips []string
174 var err error
175
176 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
177
178 if addr = net.ParseIP(host); addr == nil {
179 log.Debugw("looking-up-hostname", log.Fields{"host": host})
180
181 if ips, err = net.LookupHost(host); err == nil {
182 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
183 if addr = net.ParseIP(ips[0]); addr == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530184 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400185 }
186 genmac = macifyIP(addr)
187 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
188 return genmac, nil
189 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530190 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", nil, err).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400191 }
192
193 genmac = macifyIP(addr)
194 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
195 return genmac, nil
196}
197
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530198func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700199 slist := strings.Split(mac, ":")
200 result := make([]uint32, len(slist))
201 var err error
202 var tmp int64
203 for index, val := range slist {
204 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
205 return []uint32{1, 2, 3, 4, 5, 6}
206 }
207 result[index] = uint32(tmp)
208 }
209 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530210}
211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700212//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 -0800213func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530214
David K. Bainbridge794735f2020-02-11 21:01:37 -0800215 switch portType {
216 case voltha.Port_ETHERNET_NNI:
217 return fmt.Sprintf("nni-%d", portNum), nil
218 case voltha.Port_PON_OLT:
219 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700220 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800221
Thomas Lee S94109f12020-03-03 16:39:29 +0530222 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil).Log()
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530223}
224
David K. Bainbridge794735f2020-02-11 21:01:37 -0800225func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000226 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700227 if state == "up" {
228 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500229 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500230 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700231 } else {
232 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500233 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700234 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700235 portNum := IntfIDToPortNo(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800236 label, err := GetportLabel(portNum, portType)
237 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530238 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, nil).Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -0400239 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500240
241 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
242 if err != nil || device == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530243 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500244 }
245 if device.Ports != nil {
246 for _, dPort := range device.Ports {
247 if dPort.Type == portType && dPort.PortNo == portNum {
248 log.Debug("port-already-exists-updating-oper-status-of-port")
249 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530250 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800251 "device-id": dh.device.Id,
252 "port-type": portType,
253 "port-number": portNum,
254 "oper-status": operStatus}, err).Log()
255
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500256 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800257 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500258 }
259 }
260 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400261 // Now create Port
262 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700263 PortNo: portNum,
264 Label: label,
265 Type: portType,
266 OperStatus: operStatus,
267 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500268 log.Debugw("Sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700269 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700270 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530271 return olterrors.NewErrAdapter("Error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800272 "device-id": dh.device.Id,
273 "port-type": portType}, err).Log()
Girish Gowdru1110ef22019-06-24 11:17:59 -0400274 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800275 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530276}
277
278// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800279func (dh *DeviceHandler) readIndications(ctx context.Context) error {
280 defer log.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530281 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700282 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530283 return olterrors.NewErrCommunication("fail-to-read-indications", log.Fields{"device-id": dh.device.Id}, err).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700284 }
285 if indications == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530286 return olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700287 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400288 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530289 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400290 if err != nil || device == nil {
291 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530292 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400293 }
294 // When the device is in DISABLED and Adapter container restarts, we need to
295 // rebuild the locally maintained admin state.
296 if device.AdminState == voltha.AdminState_DISABLED {
297 dh.lockDevice.Lock()
298 dh.adminState = "down"
299 dh.lockDevice.Unlock()
300 }
301
David Bainbridgef5879ca2019-12-13 21:17:54 +0000302 // Create an exponential backoff around re-enabling indications. The
303 // maximum elapsed time for the back off is set to 0 so that we will
304 // continue to retry. The max interval defaults to 1m, but is set
305 // here for code clarity
306 indicationBackoff := backoff.NewExponentialBackOff()
307 indicationBackoff.MaxElapsedTime = 0
308 indicationBackoff.MaxInterval = 1 * time.Minute
cuilin20187b2a8c32019-03-26 19:52:28 -0700309 for {
310 indication, err := indications.Recv()
311 if err == io.EOF {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530312 log.Infow("EOF for indications", log.Fields{"err": err})
David Bainbridgef5879ca2019-12-13 21:17:54 +0000313 // Use an exponential back off to prevent getting into a tight loop
314 duration := indicationBackoff.NextBackOff()
315 if duration == backoff.Stop {
316 // If we reach a maximum then warn and reset the backoff
317 // timer and keep attempting.
318 log.Warnw("Maximum indication backoff reached, resetting backoff timer",
319 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
320 indicationBackoff.Reset()
321 }
322 time.Sleep(indicationBackoff.NextBackOff())
npujarec5762e2020-01-01 14:08:48 +0530323 indications, err = dh.Client.EnableIndication(ctx, new(oop.Empty))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530324 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530325 return olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530326 }
327 continue
cuilin20187b2a8c32019-03-26 19:52:28 -0700328 }
329 if err != nil {
330 log.Infow("Failed to read from indications", log.Fields{"err": err})
Devmalya Paul495b94a2019-08-27 19:42:00 -0400331 if dh.adminState == "deleted" {
332 log.Debug("Device deleted stoping the read indication thread")
333 break
334 }
npujarec5762e2020-01-01 14:08:48 +0530335 dh.transitionMap.Handle(ctx, DeviceDownInd)
336 dh.transitionMap.Handle(ctx, DeviceInit)
Thomas Lee S94109f12020-03-03 16:39:29 +0530337 return olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700338 }
David Bainbridgef5879ca2019-12-13 21:17:54 +0000339 // Reset backoff if we have a successful receive
340 indicationBackoff.Reset()
Chaitrashree G S44124192019-08-07 20:21:36 -0400341 dh.lockDevice.RLock()
342 adminState := dh.adminState
343 dh.lockDevice.RUnlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400344 // When OLT is admin down, ignore all indications.
Chaitrashree G S44124192019-08-07 20:21:36 -0400345 if adminState == "down" {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530346
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +0530347 log.Infow("olt is admin down, ignore indication", log.Fields{"indication": indication})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400348 continue
349 }
npujarec5762e2020-01-01 14:08:48 +0530350 dh.handleIndication(ctx, indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530351
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700352 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800353 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700354}
355
David K. Bainbridge794735f2020-02-11 21:01:37 -0800356func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000357 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000358 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530359 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700360 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530361 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700362 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000363 // Send or clear Alarm
David K. Bainbridge794735f2020-02-11 21:01:37 -0800364 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530365 return olterrors.NewErrAdapter("failed-indication", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800366 "device_id": dh.deviceID,
367 "indication": oltIndication,
368 "timestamp": raisedTs}, err).Log()
369 }
370 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700371}
372
David K. Bainbridge794735f2020-02-11 21:01:37 -0800373// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530374func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400375 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700376 switch indication.Data.(type) {
377 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800378 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530379 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800380 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700381 case *oop.Indication_IntfInd:
382 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800383 go func() {
384 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530385 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800386 }
387 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700388 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
389 case *oop.Indication_IntfOperInd:
390 intfOperInd := indication.GetIntfOperInd()
391 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800392 go func() {
393 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530394 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800395 }
396 }()
npujarec5762e2020-01-01 14:08:48 +0530397 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700398 } else if intfOperInd.GetType() == "pon" {
399 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
400 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800401 go func() {
402 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530403 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800404 }
405 }()
kesavand39e0aa32020-01-28 20:58:50 -0500406 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700407 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700408 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
409 case *oop.Indication_OnuDiscInd:
410 onuDiscInd := indication.GetOnuDiscInd()
411 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700412 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800413 go func() {
414 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530415 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800416 }
417 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700418 case *oop.Indication_OnuInd:
419 onuInd := indication.GetOnuInd()
420 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800421 go func() {
422 if err := dh.onuIndication(onuInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530423 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800424 }
425 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700426 case *oop.Indication_OmciInd:
427 omciInd := indication.GetOmciInd()
lcuie24ef182019-04-29 22:58:36 -0700428 log.Debugw("Received Omci indication ", log.Fields{"IntfId": omciInd.IntfId, "OnuId": omciInd.OnuId, "pkt": hex.EncodeToString(omciInd.Pkt)})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800429 go func() {
430 if err := dh.omciIndication(omciInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530431 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800432 }
433 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700434 case *oop.Indication_PktInd:
435 pktInd := indication.GetPktInd()
436 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800437 go func() {
438 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530439 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800440 }
441 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700442 case *oop.Indication_PortStats:
443 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530444 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700445 case *oop.Indication_FlowStats:
446 flowStats := indication.GetFlowStats()
447 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
448 case *oop.Indication_AlarmInd:
449 alarmInd := indication.GetAlarmInd()
450 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530451 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700452 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530453}
454
455// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530456func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400457 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530458 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400459 voltha.OperStatus_ACTIVE); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530460 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -0400461 }
462 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530463}
464
465// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530466func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700467 dh.lockDevice.Lock()
468 defer dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400469 log.Debug("do-state-down-start")
470
npujarec5762e2020-01-01 14:08:48 +0530471 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400472 if err != nil || device == nil {
473 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530474 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrud4245152019-05-10 00:47:31 -0400475 }
476
477 cloned := proto.Clone(device).(*voltha.Device)
478 // Update the all ports state on that device to disable
David K. Bainbridge794735f2020-02-11 21:01:37 -0800479 if err = dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530480 return olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": device.Id}, err).Log()
Girish Gowdrud4245152019-05-10 00:47:31 -0400481 }
482
483 //Update the device oper state and connection status
484 cloned.OperStatus = voltha.OperStatus_UNKNOWN
485 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
486 dh.device = cloned
487
David K. Bainbridge794735f2020-02-11 21:01:37 -0800488 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530489 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err).Log()
Girish Gowdrud4245152019-05-10 00:47:31 -0400490 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400491
492 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530493 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400494 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530495 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400496 }
497 for _, onuDevice := range onuDevices.Items {
498
499 // Update onu state as down in onu adapter
500 onuInd := oop.OnuIndication{}
501 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800502 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700503 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800504 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530505 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800506 "source": "openolt",
507 "onu-indicator": onuInd,
508 "device-type": onuDevice.Type,
509 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700510 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700511 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400512 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700513 /* Discovered ONUs entries need to be cleared , since after OLT
514 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530515 dh.discOnus = sync.Map{}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800516 log.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700517 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530518}
519
520// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530521func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400522 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800523 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530524 return olterrors.NewErrCommunication("dial-failure", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800525 "device-id": dh.deviceID,
526 "host-and-port": dh.device.GetHostAndPort()}, err).Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -0400527 }
528 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530529}
530
531// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530532func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400533 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530534 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400535 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530536}
537
538// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530539func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400540 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400541
542 // Case where OLT is disabled and then rebooted.
543 if dh.adminState == "down" {
544 log.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530545 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400546 if err != nil || device == nil {
547 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530548 olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400549 }
550
551 cloned := proto.Clone(device).(*voltha.Device)
552 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
553 cloned.OperStatus = voltha.OperStatus_UNKNOWN
554 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530555 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530556 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400557 }
558
Chaitrashree G S44124192019-08-07 20:21:36 -0400559 // 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 +0530560 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400561 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530562 olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400563 }
564
565 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800566 go func() {
567 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530568 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800569 }
570 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400571 return nil
572 }
573
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400574 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700575 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530576 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700577 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400578
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700579 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400580 if err != nil || device == nil {
581 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530582 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrud4245152019-05-10 00:47:31 -0400583 }
kesavand39e0aa32020-01-28 20:58:50 -0500584 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500585 if err := dh.disableAdminDownPorts(device); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530586 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err).Log()
Girish Gowdrud4245152019-05-10 00:47:31 -0400587 }
588
Girish Gowdru0c588b22019-04-23 23:24:56 -0400589 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
590 // Instantiate resource manager
npujarec5762e2020-01-01 14:08:48 +0530591 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530592 return olterrors.ErrResourceManagerInstantiating.Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -0400593 }
594 // Instantiate flow manager
npujarec5762e2020-01-01 14:08:48 +0530595 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530596 return olterrors.ErrResourceManagerInstantiating.Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -0400597 }
598 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400599 /* Instantiating Event Manager to handle Alarms and KPIs */
Devmalya Paul90ca3012019-09-02 21:55:45 -0400600 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
Naga Manjunath7615e552019-10-11 22:35:47 +0530601 // Stats config for new device
602 dh.portStats = NewOpenOltStatsMgr(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530603
cuilin20187b2a8c32019-03-26 19:52:28 -0700604 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800605 go func() {
606 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530607 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800608 }
609 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700610 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530611}
612
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400613func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
614 var err error
615 var deviceInfo *oop.DeviceInfo
616
617 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
618
619 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530620 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400621 }
622 if deviceInfo == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530623 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400624 }
625
626 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
627 dh.device.Root = true
628 dh.device.Vendor = deviceInfo.Vendor
629 dh.device.Model = deviceInfo.Model
630 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
631 dh.device.HardwareVersion = deviceInfo.HardwareVersion
632 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
633
634 if deviceInfo.DeviceId == "" {
635 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
636 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
637 genmac, err := generateMacFromHost(host)
638 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530639 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400640 }
641 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
642 dh.device.MacAddress = genmac
643 } else {
644 dh.device.MacAddress = deviceInfo.DeviceId
645 }
646
647 // Synchronous call to update device - this method is run in its own go routine
648 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530649 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400650 }
651
652 return deviceInfo, nil
653}
654
Naga Manjunath7615e552019-10-11 22:35:47 +0530655func startCollector(dh *DeviceHandler) {
656 // Initial delay for OLT initialization
657 time.Sleep(1 * time.Minute)
658 log.Debugf("Starting-Collector")
659 context := make(map[string]string)
660 for {
661 select {
662 case <-dh.stopCollector:
663 log.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
664 return
665 default:
666 freq := dh.metrics.ToPmConfigs().DefaultFreq
667 time.Sleep(time.Duration(freq) * time.Second)
668 context["oltid"] = dh.deviceID
669 context["devicetype"] = dh.deviceType
670 // NNI Stats
671 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
672 log.Debugf("Collect-NNI-Metrics %v", cmnni)
673 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
674 log.Debugf("Publish-NNI-Metrics")
675 // PON Stats
676 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
Chaitrashree G Sef088112020-02-03 21:39:27 -0500677 for i := uint32(0); i < NumPonPORTS; i++ {
678 if val, ok := dh.activePorts.Load(i); ok && val == true {
679 cmpon := dh.portStats.collectPONMetrics(i)
680 log.Debugf("Collect-PON-Metrics %v", cmpon)
Naga Manjunath7615e552019-10-11 22:35:47 +0530681
Chaitrashree G Sef088112020-02-03 21:39:27 -0500682 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
683 log.Debugf("Publish-PON-Metrics")
684 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530685 }
686 }
687 }
688}
689
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700690//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530691func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400692 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700693 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530694 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530695
696 // Now, set the initial PM configuration for that device
697 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530698 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530699 }
700
701 go startCollector(dh)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530702 go startHeartbeatCheck(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530703}
704
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700705//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530706func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700707 return &ic.SwitchCapability{
708 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530709 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700710 HwDesc: "open_pon",
711 SwDesc: "open_pon",
712 SerialNum: dh.device.SerialNumber,
713 },
714 SwitchFeatures: &of.OfpSwitchFeatures{
715 NBuffers: 256,
716 NTables: 2,
717 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
718 of.OfpCapabilities_OFPC_TABLE_STATS |
719 of.OfpCapabilities_OFPC_PORT_STATS |
720 of.OfpCapabilities_OFPC_GROUP_STATS),
721 },
722 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530723}
724
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700725//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530726func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700727 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700728 return &ic.PortCapability{
729 Port: &voltha.LogicalPort{
730 OfpPort: &of.OfpPort{
731 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
732 Config: 0,
733 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700734 Curr: capacity,
735 Advertised: capacity,
736 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700737 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
738 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
739 },
740 DeviceId: dh.device.Id,
741 DevicePortNo: uint32(portNo),
742 },
743 }, nil
744}
745
David K. Bainbridge794735f2020-02-11 21:01:37 -0800746func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700747 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700748 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700749 var deviceID string
750 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700751
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700752 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530753
754 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
755
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700756 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
757 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700758 kwargs := make(map[string]interface{})
759 kwargs["onu_id"] = omciInd.OnuId
760 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700761
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700762 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
763 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530764 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800765 "interface-id": omciInd.IntfId,
766 "onu-id": omciInd.OnuId}, err).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700767 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700768 deviceType = onuDevice.Type
769 deviceID = onuDevice.Id
770 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
771 //if not exist in cache, then add to cache.
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530772 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700773 } else {
774 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700775 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530776 deviceType = onuInCache.(*OnuDevice).deviceType
777 deviceID = onuInCache.(*OnuDevice).deviceID
778 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700779 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700780
781 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800782 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700783 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800784 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530785 return olterrors.NewErrCommunication("omci-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800786 "source": dh.deviceType,
787 "destination": deviceType,
788 "onu-id": deviceID,
789 "proxy-device-id": proxyDeviceID}, err).Log()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700790 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800791 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530792}
793
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700794//ProcessInterAdapterMessage sends the proxied messages to the target device
795// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
796// is meant, and then send the unmarshalled omci message to this onu
797func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
798 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700799 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700800 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700801 fromTopic := msg.Header.FromTopic
802 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700803 toDeviceID := msg.Header.ToDeviceId
804 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700805
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700806 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700807
808 msgBody := msg.GetBody()
809
810 omciMsg := &ic.InterAdapterOmciMessage{}
811 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
812 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
813 return err
814 }
815
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700816 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700817 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
818 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530819 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800820 "device-id": dh.device.Id,
821 "onu-device-id": toDeviceID}, err).Log()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700822 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700823 log.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 -0800824 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530825 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800826 "device-id": dh.device.Id,
827 "onu-device-id": toDeviceID}, err).Log()
828 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700829 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700830 log.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 -0800831 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530832 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800833 "device-id": dh.device.Id,
834 "onu-device-id": toDeviceID}, err).Log()
835 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700836 }
837
838 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530839 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700840 }
841 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530842}
843
David K. Bainbridge794735f2020-02-11 21:01:37 -0800844func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700845 var intfID uint32
846 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000847 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700848 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700849 intfID = onuDevice.ProxyAddress.GetChannelId()
850 onuID = onuDevice.ProxyAddress.GetOnuId()
851 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700852 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700853 intfID = omciMsg.GetProxyAddress().GetChannelId()
854 onuID = omciMsg.GetProxyAddress().GetOnuId()
855 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700856 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700857 if connectStatus != voltha.ConnectStatus_REACHABLE {
858 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800859
Thomas Lee S94109f12020-03-03 16:39:29 +0530860 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800861 "interface-id": intfID,
862 "onu-id": onuID}, nil).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700863 }
864
lcuie24ef182019-04-29 22:58:36 -0700865 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
866 isHexString := false
867 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
868 if decodeerr == nil {
869 isHexString = true
870 }
871
872 // TODO: OpenOLT Agent expects a hex string for OMCI packets rather than binary. Fix this in the agent and then we can pass binary Pkt: omciMsg.Message.
873 var omciMessage *oop.OmciMsg
874 if isHexString {
875 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
876 } else {
877 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
878 hex.Encode(hexPkt, omciMsg.Message)
879 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
880 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700881
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700882 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
883 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530884 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800885 "interface-id": intfID,
886 "onu-id": onuID,
887 "message": omciMessage}, err).Log()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700888 }
lcuie24ef182019-04-29 22:58:36 -0700889 log.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800890 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700891}
892
David K. Bainbridge794735f2020-02-11 21:01:37 -0800893func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700894 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
npujarec5762e2020-01-01 14:08:48 +0530895 dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700896 // TODO: need resource manager
897 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700898 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +0530899 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400900 st, _ := status.FromError(err)
901 if st.Code() == codes.AlreadyExists {
902 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
903 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530904 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu}, err).Log()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400905 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700906 } else {
907 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
908 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800909 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700910}
911
David K. Bainbridge794735f2020-02-11 21:01:37 -0800912func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800913
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700914 channelID := onuDiscInd.GetIntfId()
915 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400916
Matteo Scandolo945e4012019-12-12 14:16:11 -0800917 log.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530918
cuilin20187b2a8c32019-03-26 19:52:28 -0700919 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400920 if sn != "" {
921 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400922 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530923 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil).Log()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400924 }
925
Amit Ghoshe5c6a852020-02-10 15:09:46 +0000926 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
927 log.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800928 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +0000929 }
930
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400931 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -0800932
933 // check the ONU is already know to the OLT
934 // NOTE the second time the ONU is discovered this should return a device
935 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
936
937 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800938 log.Warnw("core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -0800939 if e, ok := status.FromError(err); ok {
940 log.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
941 switch e.Code() {
942 case codes.Internal:
943 // this probably means NOT FOUND, so just create a new device
944 onuDevice = nil
945 case codes.DeadlineExceeded:
946 // if the call times out, cleanup and exit
947 dh.discOnus.Delete(sn)
Thomas Lee S94109f12020-03-03 16:39:29 +0530948 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err).Log()
Matteo Scandolo945e4012019-12-12 14:16:11 -0800949 }
950 }
951 }
952
953 if onuDevice == nil {
954 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
955 log.Infow("creating-new-onu", log.Fields{"sn": sn})
956 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -0400957 ponintfid := onuDiscInd.GetIntfId()
958 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +0530959 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -0400960 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400961
Matteo Scandolo945e4012019-12-12 14:16:11 -0800962 log.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
963
964 if err != nil {
965 // if we can't create an ID in resource manager,
966 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -0800967 dh.discOnus.Delete(sn)
Thomas Lee S94109f12020-03-03 16:39:29 +0530968 return olterrors.NewErrAdapter("resource-manage-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800969 "pon-interface-id": ponintfid,
970 "serial-number": sn}, err).Log()
Matteo Scandolo945e4012019-12-12 14:16:11 -0800971 }
972
973 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
974 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800975 dh.discOnus.Delete(sn)
976 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 +0530977 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800978 "pon-interface-id": ponintfid,
979 "serial-number": sn}, err).Log()
Matteo Scandolo945e4012019-12-12 14:16:11 -0800980 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -0500981 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Matteo Scandolo945e4012019-12-12 14:16:11 -0800982 log.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400983 }
Matteo Scandolo945e4012019-12-12 14:16:11 -0800984
985 // we can now use the existing ONU Id
986 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -0700987 //Insert the ONU into cache to use in OnuIndication.
988 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Matteo Scandolo945e4012019-12-12 14:16:11 -0800989 log.Debugw("onu-discovery-indication-key-create", log.Fields{"onuID": onuID,
990 "intfId": onuDiscInd.GetIntfId(), "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700991 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -0400992
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530993 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
994 dh.onus.Store(onuKey, onuDev)
Matteo Scandolo945e4012019-12-12 14:16:11 -0800995 log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400996
David K. Bainbridge794735f2020-02-11 21:01:37 -0800997 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530998 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800999 "device-id": onuDevice.Id,
1000 "serial-number": sn}, err).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -07001001 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001002 log.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001003 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301004 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001005 "device-id": onuDevice.Id,
1006 "serial-number": sn}, err).Log()
1007 }
1008 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001009}
1010
David K. Bainbridge794735f2020-02-11 21:01:37 -08001011func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001012 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1013
1014 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001015 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001016 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001017 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001018 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -07001019 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
1020 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001021 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301022
David K. Bainbridge794735f2020-02-11 21:01:37 -08001023 errFields := log.Fields{"device-id": dh.device.Id}
1024
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301025 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1026
Mahir Gunyele77977b2019-06-27 05:36:22 -07001027 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1028 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001029 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1030 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001031 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001032 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1033 if serialNumber != "" {
1034 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001035 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001036 } else {
1037 kwargs["onu_id"] = onuInd.OnuId
1038 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001039 errFields["onu-id"] = onuInd.OnuId
1040 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001041 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001042 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001043 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001044
David K. Bainbridge794735f2020-02-11 21:01:37 -08001045 if err != nil || onuDevice == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301046 return olterrors.NewErrNotFound("onu-device", errFields, err).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -07001047 }
1048
David K. Bainbridge794735f2020-02-11 21:01:37 -08001049 if onuDevice.ParentPortNo != ponPort {
1050 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
1051 "previousIntfId": onuDevice.ParentPortNo,
1052 "currentIntfId": ponPort})
1053 }
1054
1055 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
1056 log.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
1057 "expected_onu_id": onuDevice.ProxyAddress.OnuId,
1058 "received_onu_id": onuInd.OnuId})
1059 }
1060 if !foundInCache {
1061 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1062
1063 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId))
1064
1065 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001066 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301067 return olterrors.NewErrCommunication("state-update-failed", errFields, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001068 }
1069 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001070}
1071
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001072func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301073 ctx := context.TODO()
Matt Jeanneret53539512019-07-20 14:47:02 -04001074 log.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001075 if onuInd.AdminState == "down" {
1076 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1077 if onuInd.OperState != "down" {
1078 log.Warnw("ONU-admin-state-down", log.Fields{"operState": onuInd.OperState})
1079 onuInd.OperState = "down"
1080 }
1081 }
1082
David K. Bainbridge794735f2020-02-11 21:01:37 -08001083 switch onuInd.OperState {
1084 case "down":
Matt Jeanneret53539512019-07-20 14:47:02 -04001085 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001086 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301087 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001088 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1089 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301090 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001091 "onu-indicator": onuInd,
1092 "source": "openolt",
1093 "device-type": onuDevice.Type,
1094 "device-id": onuDevice.Id}, err).Log()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001095 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001096 case "up":
Matt Jeanneret53539512019-07-20 14:47:02 -04001097 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
1098 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301099 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001100 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1101 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301102 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001103 "onu-indicator": onuInd,
1104 "source": "openolt",
1105 "device-type": onuDevice.Type,
1106 "device-id": onuDevice.Id}, err).Log()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001107 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001108 default:
Thomas Lee S94109f12020-03-03 16:39:29 +05301109 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil).Log()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001110 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001111 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001112}
1113
cuilin20187b2a8c32019-03-26 19:52:28 -07001114func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1115 if serialNum != nil {
1116 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001117 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001118 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001119}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001120func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1121 decodedStr, err := hex.DecodeString(serialNum[4:])
1122 if err != nil {
1123 return nil, err
1124 }
1125 return &oop.SerialNumber{
1126 VendorId: []byte(serialNum[:4]),
1127 VendorSpecific: []byte(decodedStr),
1128 }, nil
1129}
cuilin20187b2a8c32019-03-26 19:52:28 -07001130
1131func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1132 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001133 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001134 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1135 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1136 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1137 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1138 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1139 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1140 return tmp
1141}
1142
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001143//UpdateFlowsBulk upates the bulk flow
1144func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301145 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001146}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001147
1148//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001149func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001150 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001151 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001152 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001153 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001154 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001155 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301156 return nil, olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001157 "interface-id": parentPort,
1158 "onu-id": onuID}, err).Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -04001159 }
1160 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001161 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301162}
1163
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001164// SendPacketInToCore sends packet-in to core
1165// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1166// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001167func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001168 log.Debugw("send-packet-in-to-core", log.Fields{
1169 "port": logicalPort,
1170 "packet": hex.EncodeToString(packetPayload),
1171 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001172 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301173 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001174 "source": "adapter",
1175 "destination": "core",
1176 "device-id": dh.device.Id,
1177 "logical-port": logicalPort,
1178 "packet": hex.EncodeToString(packetPayload)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001179 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001180 log.Debugw("Sent packet-in to core successfully", log.Fields{
1181 "packet": hex.EncodeToString(packetPayload),
1182 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001183 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001184}
1185
A R Karthick1f85b802019-10-11 05:06:05 +00001186// AddUniPortToOnu adds the uni port to the onu device
1187func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1188 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301189
1190 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001191 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301192 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1193 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001194 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1195 }
1196 }
1197}
1198
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001199//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301200func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001201 log.Debugw("Received-incremental-flowupdate-in-device-handler", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001202
1203 var errorsList []error
1204
Girish Gowdru0c588b22019-04-23 23:24:56 -04001205 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001206 for _, flow := range flows.ToRemove.Items {
1207 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
npujarec5762e2020-01-01 14:08:48 +05301208 dh.flowMgr.RemoveFlow(ctx, flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001209 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301210
1211 for _, flow := range flows.ToAdd.Items {
1212 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001213 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1214 if err != nil {
1215 errorsList = append(errorsList, err)
1216 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301217 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001218 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001219 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001220 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001221 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001222 // dh.flowMgr.RemoveFlow(flow)
1223 }
1224 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001225
1226 if groups != nil {
1227 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001228 err := dh.flowMgr.AddGroup(ctx, group)
1229 if err != nil {
1230 errorsList = append(errorsList, err)
1231 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001232 }
1233 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001234 err := dh.flowMgr.ModifyGroup(ctx, group)
1235 if err != nil {
1236 errorsList = append(errorsList, err)
1237 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001238 }
1239 if len(groups.ToRemove.Items) != 0 {
1240 log.Debug("Group delete operation is not supported for now")
1241 }
1242 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001243 if len(errorsList) > 0 {
1244 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1245 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001246 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001247 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301248}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001249
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001250//DisableDevice disables the given device
1251//It marks the following for the given device:
1252//Device-Handler Admin-State : down
1253//Device Port-State: UNKNOWN
1254//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001255func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001256 /* On device disable ,admin state update has to be done prior sending request to agent since
1257 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001258 dh.lockDevice.Lock()
1259 dh.adminState = "down"
1260 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001261 if dh.Client != nil {
1262 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1263 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001264 dh.lockDevice.Lock()
1265 dh.adminState = "up"
1266 dh.lockDevice.Unlock()
Thomas Lee S94109f12020-03-03 16:39:29 +05301267 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err).Log()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001268 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001269 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001270 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001271 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001272 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001273 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301274
1275 dh.discOnus = sync.Map{}
1276 dh.onus = sync.Map{}
1277
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301278 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001279 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001280 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1281 for _, port := range cloned.Ports {
1282 if port.GetType() == voltha.Port_PON_OLT {
1283 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1284 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
1285 return err
1286 }
1287 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001288 }
1289
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001290 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001291 return nil
1292}
1293
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301294func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001295
1296 // Update onu state as unreachable in onu adapter
1297 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301298 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001299 //get the child device for the parent device
1300 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1301 if err != nil {
1302 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1303 }
1304 if onuDevices != nil {
1305 for _, onuDevice := range onuDevices.Items {
1306 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1307 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1308 if err != nil {
1309 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1310 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1311 }
1312
1313 }
1314 }
1315
1316}
1317
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001318//ReenableDevice re-enables the olt device after disable
1319//It marks the following for the given device:
1320//Device-Handler Admin-State : up
1321//Device Port-State: ACTIVE
1322//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001323func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001324 dh.lockDevice.Lock()
1325 dh.adminState = "up"
1326 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301327
1328 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1329 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301330 dh.lockDevice.Lock()
1331 dh.adminState = "down"
1332 dh.lockDevice.Unlock()
Thomas Lee S94109f12020-03-03 16:39:29 +05301333 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301334 }
1335 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001336 log.Debug("olt-reenabled")
1337
1338 cloned := proto.Clone(device).(*voltha.Device)
1339 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001340
kdarapu1afeceb2020-02-12 01:38:09 -05001341 if err := dh.disableAdminDownPorts(device); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301342 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err).Log()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001343 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001344 //Update the device oper status as ACTIVE
1345 cloned.OperStatus = voltha.OperStatus_ACTIVE
1346 dh.device = cloned
1347
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001348 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301349 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001350 "device-id": device.Id,
1351 "connect-status": cloned.ConnectStatus,
1352 "oper-status": cloned.OperStatus}, err).Log()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001353 }
kesavand39e0aa32020-01-28 20:58:50 -05001354
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001355 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001356
1357 return nil
1358}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001359
npujarec5762e2020-01-01 14:08:48 +05301360func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001361 var uniID uint32
1362 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301363 for _, port := range onu.UniPorts {
1364 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001365 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1366 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301367 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301368 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001369 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301370 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301371 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001372 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301373 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001374 }
npujarec5762e2020-01-01 14:08:48 +05301375 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001376 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301377 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301378 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001379 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301380 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301381 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301382 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001383 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301384 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1385 }
npujarec5762e2020-01-01 14:08:48 +05301386 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1387 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301388 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1389 }
1390 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301391 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301392 log.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 +00001393 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001394 }
1395 return nil
1396}
1397
npujarec5762e2020-01-01 14:08:48 +05301398func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001399 nniUniID := -1
1400 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301401
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001402 if dh.resourceMgr == nil {
1403 return fmt.Errorf("no resource manager for deviceID %s", dh.deviceID)
1404 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001405 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301406 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301407 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301408 return olterrors.NewErrPersistence("get", "nni", 0, nil, err).Log()
Devmalya Paul495b94a2019-08-27 19:42:00 -04001409 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301410 log.Debugw("NNI are ", log.Fields{"nni": nni})
1411 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301412 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301413 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1414 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301415 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301416 }
npujarec5762e2020-01-01 14:08:48 +05301417 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001418 }
npujarec5762e2020-01-01 14:08:48 +05301419 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301420 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301421 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001422 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001423}
1424
1425// 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 +05301426func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001427 log.Debug("Function entry delete device")
1428 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001429 if dh.adminState == "deleted" {
1430 dh.lockDevice.Unlock()
1431 return nil
1432 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001433 dh.adminState = "deleted"
1434 dh.lockDevice.Unlock()
1435 /* Clear the KV store data associated with the all the UNI ports
1436 This clears up flow data and also resource map data for various
1437 other pon resources like alloc_id and gemport_id
1438 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001439 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301440 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1441 var ponPort uint32
1442 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1443 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301444 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301445 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301446 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001447 "device-id": dh.device.Id,
1448 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301449 }
1450 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301451 onuID := make([]uint32, 1)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301452 log.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301453 if err = dh.clearUNIData(ctx, &onu); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301454 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1455 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301456 // Clear flowids for gem cache.
1457 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301458 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301459 }
1460 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301461 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301462 }
npujarec5762e2020-01-01 14:08:48 +05301463 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301464 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301465 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301466 if err != nil {
1467 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001468 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001469 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001470 /* Clear the flows from KV store associated with NNI port.
1471 There are mostly trap rules from NNI port (like LLDP)
1472 */
npujarec5762e2020-01-01 14:08:48 +05301473 if err := dh.clearNNIData(ctx); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301474 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001475 }
A R Karthick1f85b802019-10-11 05:06:05 +00001476
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001477 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301478 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001479 }
A R Karthick1f85b802019-10-11 05:06:05 +00001480
Devmalya Paul495b94a2019-08-27 19:42:00 -04001481 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301482 dh.onus.Range(func(key interface{}, value interface{}) bool {
1483 dh.onus.Delete(key)
1484 return true
1485 })
1486
Devmalya Paul495b94a2019-08-27 19:42:00 -04001487 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301488 // Stop the Stats collector
1489 dh.stopCollector <- true
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301490 // stop the heartbeat check routine
1491 dh.stopHeartbeatCheck <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001492 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001493 if dh.Client != nil {
npujarec5762e2020-01-01 14:08:48 +05301494 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301495 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001496 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001497 }
1498 cloned := proto.Clone(device).(*voltha.Device)
1499 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1500 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
npujarec5762e2020-01-01 14:08:48 +05301501 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301502 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001503 "device-id": device.Id,
1504 "connect-status": cloned.ConnectStatus,
1505 "oper-status": cloned.OperStatus}, err).Log()
Devmalya Paul495b94a2019-08-27 19:42:00 -04001506 }
1507 return nil
1508}
1509
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001510//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001511func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1512 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301513 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001514 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001515 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001516 return nil
1517}
1518
David K. Bainbridge794735f2020-02-11 21:01:37 -08001519func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001520 log.Debugw("Received packet-in", log.Fields{
1521 "packet-indication": *packetIn,
1522 "packet": hex.EncodeToString(packetIn.Pkt),
1523 })
npujarec5762e2020-01-01 14:08:48 +05301524 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001525 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301526 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001527 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001528 log.Debugw("sending packet-in to core", log.Fields{
1529 "logicalPortNum": logicalPortNum,
1530 "packet": hex.EncodeToString(packetIn.Pkt),
1531 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001532 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301533 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001534 "destination": "core",
1535 "source": dh.deviceType,
1536 "packet": hex.EncodeToString(packetIn.Pkt)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001537 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001538 log.Debugw("Success sending packet-in to core!", log.Fields{
1539 "packet": hex.EncodeToString(packetIn.Pkt),
1540 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001541 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001542}
1543
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001544// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301545func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001546 log.Debugw("incoming-packet-out", log.Fields{
1547 "deviceID": dh.deviceID,
1548 "egress_port_no": egressPortNo,
1549 "pkt-length": len(packet.Data),
1550 "packet": hex.EncodeToString(packet.Data),
1551 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001552
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001553 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001554 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001555 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1556 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301557 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1558 // Do not packet-out lldp packets on uni port.
1559 // ONOS has no clue about uni/nni ports, it just packets out on all
1560 // available ports on the Logical Switch. It should not be interested
1561 // in the UNI links.
1562 log.Debug("dropping-lldp-packet-out-on-uni")
1563 return nil
1564 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001565 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1566 if innerEthType == 0x8100 {
1567 // q-in-q 802.1ad or 802.1q double tagged packet.
1568 // slice out the outer tag.
1569 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1570 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001571 }
1572 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001573 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1574 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001575 uniID := UniIDFromPortNum(uint32(egressPortNo))
1576
npujarec5762e2020-01-01 14:08:48 +05301577 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001578 if err != nil {
1579 // In this case the openolt agent will receive the gemPortID as 0.
1580 // The agent tries to retrieve the gemPortID in this case.
1581 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001582 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1583 "packet": hex.EncodeToString(packet.Data),
1584 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001585 }
1586
1587 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001588
Matteo Scandolo6056e822019-11-13 14:05:29 -08001589 log.Debugw("sending-packet-to-onu", log.Fields{
1590 "egress_port_no": egressPortNo,
1591 "IntfId": intfID,
1592 "onuID": onuID,
1593 "uniID": uniID,
1594 "gemPortID": gemPortID,
1595 "packet": hex.EncodeToString(packet.Data),
1596 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001597
npujarec5762e2020-01-01 14:08:48 +05301598 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301599 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001600 "source": "adapter",
1601 "destination": "onu",
1602 "egress-port-number": egressPortNo,
1603 "interface-id": intfID,
1604 "oni-id": onuID,
1605 "uni-id": uniID,
1606 "gem-port-id": gemPortID,
1607 "packet": hex.EncodeToString(packet.Data)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001608 }
1609 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001610 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1611 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301612 return olterrors.NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001613 }
1614 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001615
Matteo Scandolo6056e822019-11-13 14:05:29 -08001616 log.Debugw("sending-packet-to-nni", log.Fields{
1617 "uplink_pkt": uplinkPkt,
1618 "packet": hex.EncodeToString(packet.Data),
1619 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001620
npujarec5762e2020-01-01 14:08:48 +05301621 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301622 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001623 }
1624 } else {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001625 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1626 "egress_port_no": egressPortNo,
1627 "egressPortType": egressPortType,
1628 "packet": hex.EncodeToString(packet.Data),
1629 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001630 }
1631 return nil
1632}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001633
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001634func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1635 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001636}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301637
1638func startHeartbeatCheck(dh *DeviceHandler) {
1639 // start the heartbeat check towards the OLT.
1640 var timerCheck *time.Timer
1641
1642 for {
1643 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1644 select {
1645 case <-heartbeatTimer.C:
1646 ctx, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1647 if heartBeat, err := dh.Client.HeartbeatCheck(ctx, new(oop.Empty)); err != nil {
1648 log.Error("Hearbeat failed")
1649 if timerCheck == nil {
1650 // start a after func, when expired will update the state to the core
1651 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, dh.updateStateUnreachable)
1652 }
1653 } else {
1654 if timerCheck != nil {
1655 if timerCheck.Stop() {
1656 log.Debug("We got hearbeat within the timeout")
1657 } else {
1658
1659 log.Debug("We got hearbeat after the timeout expired, changing the states")
1660 go dh.notifyChildDevices("up")
npujarec5762e2020-01-01 14:08:48 +05301661 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301662 voltha.OperStatus_ACTIVE); err != nil {
1663 log.Errorw("Failed to update device state", log.Fields{"deviceID": dh.device.Id, "error": err})
1664 }
1665 }
1666 timerCheck = nil
1667 }
1668 log.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
1669 }
1670 cancel()
1671 case <-dh.stopHeartbeatCheck:
1672 log.Debug("Stopping heart beat check")
1673 return
1674 }
1675 }
1676}
1677
1678func (dh *DeviceHandler) updateStateUnreachable() {
1679
1680 go dh.notifyChildDevices("unreachable")
1681 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301682 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301683 }
1684}
kesavand39e0aa32020-01-28 20:58:50 -05001685
1686// EnablePort to enable Pon interface
1687func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
1688 log.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001689 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001690}
1691
1692// DisablePort to disable pon interface
1693func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
1694 log.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001695 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001696}
1697
kdarapu1afeceb2020-02-12 01:38:09 -05001698//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1699func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301700 ctx := context.Background()
kdarapu1afeceb2020-02-12 01:38:09 -05001701 log.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort})
kesavand39e0aa32020-01-28 20:58:50 -05001702 if port.GetType() == voltha.Port_ETHERNET_NNI {
1703 // Bug is opened for VOL-2505 to support NNI disable feature.
1704 log.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
1705 log.Fields{"Device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301706 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001707 "port-type": port.GetType,
1708 "enable-state": enablePort}, nil).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001709 }
1710 // fetch interfaceid from PortNo
1711 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1712 ponIntf := &oop.Interface{IntfId: ponID}
1713 var operStatus voltha.OperStatus_Types
1714 if enablePort {
1715 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301716 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001717
1718 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301719 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001720 "device-id": dh.device.Id,
1721 "port": port}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001722 }
1723 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001724 dh.activePorts.Store(ponID, true)
kesavand39e0aa32020-01-28 20:58:50 -05001725 log.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1726 } else {
1727 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301728 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001729 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301730 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001731 "device-id": dh.device.Id,
1732 "port": port}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001733 }
1734 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001735 dh.activePorts.Store(ponID, false)
kesavand39e0aa32020-01-28 20:58:50 -05001736 log.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1737 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001738 if err := dh.coreProxy.PortStateUpdate(ctx, dh.deviceID, voltha.Port_PON_OLT, port.PortNo, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301739 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001740 "device-id": dh.deviceID,
1741 "port": port.PortNo}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001742 }
1743 return nil
1744}
1745
kdarapu1afeceb2020-02-12 01:38:09 -05001746//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1747func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001748 cloned := proto.Clone(device).(*voltha.Device)
1749 // Disable the port and update the oper_port_status to core
1750 // if the Admin state of the port is disabled on reboot and re-enable device.
1751 for _, port := range cloned.Ports {
1752 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001753 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301754 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001755 "device-id": dh.deviceID,
1756 "port": port}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001757 }
1758 }
1759 }
1760 return nil
1761}
1762
1763//populateActivePorts to populate activePorts map
1764func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
1765 log.Info("populateActiveports", log.Fields{"Device": device})
1766 for _, port := range device.Ports {
1767 if port.Type == voltha.Port_ETHERNET_NNI {
1768 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001769 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001770 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001771 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001772 }
1773 }
1774 if port.Type == voltha.Port_PON_OLT {
1775 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001776 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001777 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001778 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001779 }
1780 }
1781 }
1782}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001783
1784// ChildDeviceLost deletes ONU and clears pon resources related to it.
1785func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
1786 log.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
1787 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1788 onuKey := dh.formOnuKey(IntfID, onuID)
1789 onuDevice, ok := dh.onus.Load(onuKey)
1790 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301791 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001792 log.Fields{
1793 "device-id": dh.deviceID,
1794 "onu-id": onuID,
1795 "interface-id": IntfID}, nil).Log()
1796 }
1797 var sn *oop.SerialNumber
1798 var err error
1799 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301800 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001801 log.Fields{
1802 "devicer-id": dh.deviceID,
1803 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
1804 }
1805 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
1806 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301807 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001808 "device-id": dh.deviceID,
1809 "onu-id": onuID}, err).Log()
1810 }
1811 //clear PON resources associated with ONU
1812 var onuGemData []rsrcMgr.OnuGemInfo
1813 if err := dh.resourceMgr.ResourceMgrs[IntfID].GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001814 log.Warnw("Failed-to-get-onu-info-for-pon-port ", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001815 "device-id": dh.deviceID,
1816 "interface-id": IntfID,
1817 "error": err})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001818 } else {
1819 for i, onu := range onuGemData {
1820 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
1821 log.Debugw("onu-data ", log.Fields{"onu": onu})
1822 if err := dh.clearUNIData(ctx, &onu); err != nil {
1823 log.Warnw("Failed-to-clear-uni-data-for-onu", log.Fields{
1824 "device-id": dh.deviceID,
1825 "onu-device": onu,
1826 "error": err})
1827 }
1828 // Clear flowids for gem cache.
1829 for _, gem := range onu.GemPorts {
1830 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
1831 }
1832 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
1833 dh.resourceMgr.UpdateOnuGemInfo(ctx, IntfID, onuGemData)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001834
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001835 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
1836 break
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001837 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001838 }
1839 }
1840 dh.onus.Delete(onuKey)
1841 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
1842 return nil
1843}