blob: 0e8d4603306954578ebb21589ef2f86829b13813 [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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000184 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
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 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000190 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
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
Girish Kumarf26e4882020-03-05 06:49:10 +0000222 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000238 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000243 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
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,
Girish Kumarf26e4882020-03-05 06:49:10 +0000254 "oper-status": operStatus}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800255
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000271 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800272 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000273 "port-type": portType}, err)
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000283 return olterrors.NewErrCommunication("fail-to-read-indications", log.Fields{"device-id": dh.device.Id}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700284 }
285 if indications == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000286 return olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil)
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 */
Girish Kumarf26e4882020-03-05 06:49:10 +0000292 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000325 return olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err)
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)
Girish Kumarf26e4882020-03-05 06:49:10 +0000337 return olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err)
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,
Girish Kumarf26e4882020-03-05 06:49:10 +0000368 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800369 }
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000460 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
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 */
Girish Kumarf26e4882020-03-05 06:49:10 +0000474 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000480 return olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": device.Id}, err)
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000489 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000495 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
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,
Girish Kumarf26e4882020-03-05 06:49:10 +0000526 "host-and-port": dh.device.GetHostAndPort()}, err)
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000576 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
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 */
Girish Kumarf26e4882020-03-05 06:49:10 +0000582 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000586 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000592 return olterrors.ErrResourceManagerInstantiating
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000596 return olterrors.ErrResourceManagerInstantiating
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000620 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400621 }
622 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000623 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000639 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000649 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
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,
Girish Kumarf26e4882020-03-05 06:49:10 +0000766 "onu-id": omciInd.OnuId}, err)
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,
Girish Kumarf26e4882020-03-05 06:49:10 +0000789 "proxy-device-id": proxyDeviceID}, err)
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 {
Girish Kumarf26e4882020-03-05 06:49:10 +0000812 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700813 }
814
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700815 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700816 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
817 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530818 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800819 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000820 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700821 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700822 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 -0800823 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530824 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800825 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000826 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800827 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700828 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700829 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 -0800830 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530831 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800832 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000833 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800834 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700835 }
836
837 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000838 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700839 }
840 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530841}
842
David K. Bainbridge794735f2020-02-11 21:01:37 -0800843func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700844 var intfID uint32
845 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000846 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700847 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700848 intfID = onuDevice.ProxyAddress.GetChannelId()
849 onuID = onuDevice.ProxyAddress.GetOnuId()
850 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700851 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700852 intfID = omciMsg.GetProxyAddress().GetChannelId()
853 onuID = omciMsg.GetProxyAddress().GetOnuId()
854 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700855 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700856 if connectStatus != voltha.ConnectStatus_REACHABLE {
857 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800858
Thomas Lee S94109f12020-03-03 16:39:29 +0530859 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800860 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000861 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700862 }
863
lcuie24ef182019-04-29 22:58:36 -0700864 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
865 isHexString := false
866 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
867 if decodeerr == nil {
868 isHexString = true
869 }
870
871 // 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.
872 var omciMessage *oop.OmciMsg
873 if isHexString {
874 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
875 } else {
876 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
877 hex.Encode(hexPkt, omciMsg.Message)
878 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
879 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700880
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700881 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
882 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530883 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800884 "interface-id": intfID,
885 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000886 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700887 }
lcuie24ef182019-04-29 22:58:36 -0700888 log.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800889 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700890}
891
David K. Bainbridge794735f2020-02-11 21:01:37 -0800892func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700893 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
npujarec5762e2020-01-01 14:08:48 +0530894 dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700895 // TODO: need resource manager
896 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700897 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +0530898 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400899 st, _ := status.FromError(err)
900 if st.Code() == codes.AlreadyExists {
901 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
902 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000903 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400904 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700905 } else {
906 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
907 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800908 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700909}
910
David K. Bainbridge794735f2020-02-11 21:01:37 -0800911func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800912
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700913 channelID := onuDiscInd.GetIntfId()
914 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400915
Matteo Scandolo945e4012019-12-12 14:16:11 -0800916 log.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530917
cuilin20187b2a8c32019-03-26 19:52:28 -0700918 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400919 if sn != "" {
920 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400921 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000922 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400923 }
924
Amit Ghoshe5c6a852020-02-10 15:09:46 +0000925 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
926 log.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800927 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +0000928 }
929
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400930 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -0800931
932 // check the ONU is already know to the OLT
933 // NOTE the second time the ONU is discovered this should return a device
934 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
935
936 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800937 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 -0800938 if e, ok := status.FromError(err); ok {
939 log.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
940 switch e.Code() {
941 case codes.Internal:
942 // this probably means NOT FOUND, so just create a new device
943 onuDevice = nil
944 case codes.DeadlineExceeded:
945 // if the call times out, cleanup and exit
946 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +0000947 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -0800948 }
949 }
950 }
951
952 if onuDevice == nil {
953 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
954 log.Infow("creating-new-onu", log.Fields{"sn": sn})
955 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -0400956 ponintfid := onuDiscInd.GetIntfId()
957 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +0530958 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -0400959 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400960
Matteo Scandolo945e4012019-12-12 14:16:11 -0800961 log.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
962
963 if err != nil {
964 // if we can't create an ID in resource manager,
965 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -0800966 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +0000967 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800968 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +0000969 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -0800970 }
971
972 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
973 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800974 dh.discOnus.Delete(sn)
975 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 +0530976 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800977 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +0000978 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -0800979 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -0500980 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Matteo Scandolo945e4012019-12-12 14:16:11 -0800981 log.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400982 }
Matteo Scandolo945e4012019-12-12 14:16:11 -0800983
984 // we can now use the existing ONU Id
985 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -0700986 //Insert the ONU into cache to use in OnuIndication.
987 //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 -0800988 log.Debugw("onu-discovery-indication-key-create", log.Fields{"onuID": onuID,
989 "intfId": onuDiscInd.GetIntfId(), "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700990 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -0400991
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530992 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
993 dh.onus.Store(onuKey, onuDev)
Matteo Scandolo945e4012019-12-12 14:16:11 -0800994 log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400995
David K. Bainbridge794735f2020-02-11 21:01:37 -0800996 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530997 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800998 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000999 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001000 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001001 log.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001002 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301003 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001004 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001005 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001006 }
1007 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001008}
1009
David K. Bainbridge794735f2020-02-11 21:01:37 -08001010func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001011 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1012
1013 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001014 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001015 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001016 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001017 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -07001018 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
1019 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001020 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301021
David K. Bainbridge794735f2020-02-11 21:01:37 -08001022 errFields := log.Fields{"device-id": dh.device.Id}
1023
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301024 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1025
Mahir Gunyele77977b2019-06-27 05:36:22 -07001026 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1027 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001028 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1029 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001030 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001031 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1032 if serialNumber != "" {
1033 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001034 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001035 } else {
1036 kwargs["onu_id"] = onuInd.OnuId
1037 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001038 errFields["onu-id"] = onuInd.OnuId
1039 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001040 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001041 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001042 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001043
David K. Bainbridge794735f2020-02-11 21:01:37 -08001044 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001045 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001046 }
1047
David K. Bainbridge794735f2020-02-11 21:01:37 -08001048 if onuDevice.ParentPortNo != ponPort {
1049 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
1050 "previousIntfId": onuDevice.ParentPortNo,
1051 "currentIntfId": ponPort})
1052 }
1053
1054 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
1055 log.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
1056 "expected_onu_id": onuDevice.ProxyAddress.OnuId,
1057 "received_onu_id": onuInd.OnuId})
1058 }
1059 if !foundInCache {
1060 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1061
1062 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId))
1063
1064 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001065 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001066 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001067 }
1068 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001069}
1070
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001071func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301072 ctx := context.TODO()
Matt Jeanneret53539512019-07-20 14:47:02 -04001073 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 +00001074 if onuInd.AdminState == "down" {
1075 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1076 if onuInd.OperState != "down" {
1077 log.Warnw("ONU-admin-state-down", log.Fields{"operState": onuInd.OperState})
1078 onuInd.OperState = "down"
1079 }
1080 }
1081
David K. Bainbridge794735f2020-02-11 21:01:37 -08001082 switch onuInd.OperState {
1083 case "down":
Matt Jeanneret53539512019-07-20 14:47:02 -04001084 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 -07001085 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301086 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001087 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1088 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301089 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001090 "onu-indicator": onuInd,
1091 "source": "openolt",
1092 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001093 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001094 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001095 case "up":
Matt Jeanneret53539512019-07-20 14:47:02 -04001096 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
1097 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301098 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001099 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1100 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301101 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001102 "onu-indicator": onuInd,
1103 "source": "openolt",
1104 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001105 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001106 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001107 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001108 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001109 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001110 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001111}
1112
cuilin20187b2a8c32019-03-26 19:52:28 -07001113func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1114 if serialNum != nil {
1115 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001116 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001117 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001118}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001119func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1120 decodedStr, err := hex.DecodeString(serialNum[4:])
1121 if err != nil {
1122 return nil, err
1123 }
1124 return &oop.SerialNumber{
1125 VendorId: []byte(serialNum[:4]),
1126 VendorSpecific: []byte(decodedStr),
1127 }, nil
1128}
cuilin20187b2a8c32019-03-26 19:52:28 -07001129
1130func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1131 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001132 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001133 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1134 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1135 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1136 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1137 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1138 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1139 return tmp
1140}
1141
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001142//UpdateFlowsBulk upates the bulk flow
1143func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301144 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001145}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001146
1147//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001148func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001149 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001150 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001151 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001152 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001153 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001154 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001155 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001156 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001157 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001158 }
1159 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001160 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301161}
1162
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001163// SendPacketInToCore sends packet-in to core
1164// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1165// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001166func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001167 log.Debugw("send-packet-in-to-core", log.Fields{
1168 "port": logicalPort,
1169 "packet": hex.EncodeToString(packetPayload),
1170 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001171 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301172 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 "source": "adapter",
1174 "destination": "core",
1175 "device-id": dh.device.Id,
1176 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001177 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001178 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001179 log.Debugw("Sent packet-in to core successfully", log.Fields{
1180 "packet": hex.EncodeToString(packetPayload),
1181 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001182 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001183}
1184
A R Karthick1f85b802019-10-11 05:06:05 +00001185// AddUniPortToOnu adds the uni port to the onu device
1186func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1187 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301188
1189 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001190 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301191 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1192 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001193 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1194 }
1195 }
1196}
1197
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001198//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301199func (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 -04001200 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 +01001201
1202 var errorsList []error
1203
Girish Gowdru0c588b22019-04-23 23:24:56 -04001204 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001205 for _, flow := range flows.ToRemove.Items {
1206 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
npujarec5762e2020-01-01 14:08:48 +05301207 dh.flowMgr.RemoveFlow(ctx, flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001208 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301209
1210 for _, flow := range flows.ToAdd.Items {
1211 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001212 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1213 if err != nil {
1214 errorsList = append(errorsList, err)
1215 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301216 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001217 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001218 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001219 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001220 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001221 // dh.flowMgr.RemoveFlow(flow)
1222 }
1223 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001224
1225 if groups != nil {
1226 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001227 err := dh.flowMgr.AddGroup(ctx, group)
1228 if err != nil {
1229 errorsList = append(errorsList, err)
1230 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001231 }
1232 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001233 err := dh.flowMgr.ModifyGroup(ctx, group)
1234 if err != nil {
1235 errorsList = append(errorsList, err)
1236 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001237 }
1238 if len(groups.ToRemove.Items) != 0 {
1239 log.Debug("Group delete operation is not supported for now")
1240 }
1241 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001242 if len(errorsList) > 0 {
1243 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1244 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001245 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001246 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301247}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001248
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001249//DisableDevice disables the given device
1250//It marks the following for the given device:
1251//Device-Handler Admin-State : down
1252//Device Port-State: UNKNOWN
1253//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001254func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001255 /* On device disable ,admin state update has to be done prior sending request to agent since
1256 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001257 dh.lockDevice.Lock()
1258 dh.adminState = "down"
1259 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001260 if dh.Client != nil {
1261 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1262 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001263 dh.lockDevice.Lock()
1264 dh.adminState = "up"
1265 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001266 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001267 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001268 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001269 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001270 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001271 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001272 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301273
1274 dh.discOnus = sync.Map{}
1275 dh.onus = sync.Map{}
1276
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301277 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001278 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001279 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1280 for _, port := range cloned.Ports {
1281 if port.GetType() == voltha.Port_PON_OLT {
1282 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1283 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001284 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001285 }
1286 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001287 }
1288
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001289 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001290 return nil
1291}
1292
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301293func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001294
1295 // Update onu state as unreachable in onu adapter
1296 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301297 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001298 //get the child device for the parent device
1299 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1300 if err != nil {
1301 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1302 }
1303 if onuDevices != nil {
1304 for _, onuDevice := range onuDevices.Items {
1305 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1306 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1307 if err != nil {
1308 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1309 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1310 }
1311
1312 }
1313 }
1314
1315}
1316
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001317//ReenableDevice re-enables the olt device after disable
1318//It marks the following for the given device:
1319//Device-Handler Admin-State : up
1320//Device Port-State: ACTIVE
1321//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001322func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001323 dh.lockDevice.Lock()
1324 dh.adminState = "up"
1325 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301326
1327 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1328 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301329 dh.lockDevice.Lock()
1330 dh.adminState = "down"
1331 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001332 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301333 }
1334 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001335 log.Debug("olt-reenabled")
1336
1337 cloned := proto.Clone(device).(*voltha.Device)
1338 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001339
kdarapu1afeceb2020-02-12 01:38:09 -05001340 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001341 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001342 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001343 //Update the device oper status as ACTIVE
1344 cloned.OperStatus = voltha.OperStatus_ACTIVE
1345 dh.device = cloned
1346
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001347 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301348 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001349 "device-id": device.Id,
1350 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001351 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001352 }
kesavand39e0aa32020-01-28 20:58:50 -05001353
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001354 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001355
1356 return nil
1357}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001358
npujarec5762e2020-01-01 14:08:48 +05301359func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001360 var uniID uint32
1361 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301362 for _, port := range onu.UniPorts {
1363 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001364 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1365 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301366 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301367 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001368 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301369 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301370 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001371 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301372 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001373 }
npujarec5762e2020-01-01 14:08:48 +05301374 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001375 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301376 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301377 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001378 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301379 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301380 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301381 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001382 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301383 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1384 }
npujarec5762e2020-01-01 14:08:48 +05301385 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1386 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301387 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1388 }
1389 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301390 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301391 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 +00001392 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001393 }
1394 return nil
1395}
1396
npujarec5762e2020-01-01 14:08:48 +05301397func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001398 nniUniID := -1
1399 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301400
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001401 if dh.resourceMgr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001402 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.deviceID}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001403 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001404 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301405 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301406 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001407 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001408 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301409 log.Debugw("NNI are ", log.Fields{"nni": nni})
1410 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301411 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301412 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1413 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301414 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301415 }
npujarec5762e2020-01-01 14:08:48 +05301416 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001417 }
npujarec5762e2020-01-01 14:08:48 +05301418 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001419 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301420 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001421 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001422}
1423
1424// 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 +05301425func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001426 log.Debug("Function entry delete device")
1427 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001428 if dh.adminState == "deleted" {
1429 dh.lockDevice.Unlock()
1430 return nil
1431 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001432 dh.adminState = "deleted"
1433 dh.lockDevice.Unlock()
1434 /* Clear the KV store data associated with the all the UNI ports
1435 This clears up flow data and also resource map data for various
1436 other pon resources like alloc_id and gemport_id
1437 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001438 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301439 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1440 var ponPort uint32
1441 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1442 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301443 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301444 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301445 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001446 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001447 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301448 }
1449 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301450 onuID := make([]uint32, 1)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301451 log.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301452 if err = dh.clearUNIData(ctx, &onu); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301453 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1454 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301455 // Clear flowids for gem cache.
1456 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301457 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301458 }
1459 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301460 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301461 }
npujarec5762e2020-01-01 14:08:48 +05301462 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301463 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301464 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301465 if err != nil {
1466 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001467 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001468 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001469 /* Clear the flows from KV store associated with NNI port.
1470 There are mostly trap rules from NNI port (like LLDP)
1471 */
npujarec5762e2020-01-01 14:08:48 +05301472 if err := dh.clearNNIData(ctx); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301473 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001474 }
A R Karthick1f85b802019-10-11 05:06:05 +00001475
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001476 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301477 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001478 }
A R Karthick1f85b802019-10-11 05:06:05 +00001479
Devmalya Paul495b94a2019-08-27 19:42:00 -04001480 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301481 dh.onus.Range(func(key interface{}, value interface{}) bool {
1482 dh.onus.Delete(key)
1483 return true
1484 })
1485
Devmalya Paul495b94a2019-08-27 19:42:00 -04001486 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301487 // Stop the Stats collector
1488 dh.stopCollector <- true
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301489 // stop the heartbeat check routine
1490 dh.stopHeartbeatCheck <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001491 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001492 if dh.Client != nil {
npujarec5762e2020-01-01 14:08:48 +05301493 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001494 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001495 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001496 }
1497 cloned := proto.Clone(device).(*voltha.Device)
1498 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1499 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
npujarec5762e2020-01-01 14:08:48 +05301500 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301501 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001502 "device-id": device.Id,
1503 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001504 "oper-status": cloned.OperStatus}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001505 }
1506 return nil
1507}
1508
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001509//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001510func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1511 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001512 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001513 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001514 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001515 return nil
1516}
1517
David K. Bainbridge794735f2020-02-11 21:01:37 -08001518func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001519 log.Debugw("Received packet-in", log.Fields{
1520 "packet-indication": *packetIn,
1521 "packet": hex.EncodeToString(packetIn.Pkt),
1522 })
npujarec5762e2020-01-01 14:08:48 +05301523 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001524 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001525 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001526 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001527 log.Debugw("sending packet-in to core", log.Fields{
1528 "logicalPortNum": logicalPortNum,
1529 "packet": hex.EncodeToString(packetIn.Pkt),
1530 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001531 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301532 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001533 "destination": "core",
1534 "source": dh.deviceType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001535 "packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001536 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001537 log.Debugw("Success sending packet-in to core!", log.Fields{
1538 "packet": hex.EncodeToString(packetIn.Pkt),
1539 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001540 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001541}
1542
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001543// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301544func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001545 log.Debugw("incoming-packet-out", log.Fields{
1546 "deviceID": dh.deviceID,
1547 "egress_port_no": egressPortNo,
1548 "pkt-length": len(packet.Data),
1549 "packet": hex.EncodeToString(packet.Data),
1550 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001551
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001552 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001553 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001554 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1555 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301556 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1557 // Do not packet-out lldp packets on uni port.
1558 // ONOS has no clue about uni/nni ports, it just packets out on all
1559 // available ports on the Logical Switch. It should not be interested
1560 // in the UNI links.
1561 log.Debug("dropping-lldp-packet-out-on-uni")
1562 return nil
1563 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001564 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1565 if innerEthType == 0x8100 {
1566 // q-in-q 802.1ad or 802.1q double tagged packet.
1567 // slice out the outer tag.
1568 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1569 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001570 }
1571 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001572 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1573 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001574 uniID := UniIDFromPortNum(uint32(egressPortNo))
1575
npujarec5762e2020-01-01 14:08:48 +05301576 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001577 if err != nil {
1578 // In this case the openolt agent will receive the gemPortID as 0.
1579 // The agent tries to retrieve the gemPortID in this case.
1580 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001581 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1582 "packet": hex.EncodeToString(packet.Data),
1583 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001584 }
1585
1586 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001587
Matteo Scandolo6056e822019-11-13 14:05:29 -08001588 log.Debugw("sending-packet-to-onu", log.Fields{
1589 "egress_port_no": egressPortNo,
1590 "IntfId": intfID,
1591 "onuID": onuID,
1592 "uniID": uniID,
1593 "gemPortID": gemPortID,
1594 "packet": hex.EncodeToString(packet.Data),
1595 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001596
npujarec5762e2020-01-01 14:08:48 +05301597 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301598 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001599 "source": "adapter",
1600 "destination": "onu",
1601 "egress-port-number": egressPortNo,
1602 "interface-id": intfID,
1603 "oni-id": onuID,
1604 "uni-id": uniID,
1605 "gem-port-id": gemPortID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001606 "packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001607 }
1608 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001609 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1610 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001611 return olterrors.NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001612 }
1613 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001614
Matteo Scandolo6056e822019-11-13 14:05:29 -08001615 log.Debugw("sending-packet-to-nni", log.Fields{
1616 "uplink_pkt": uplinkPkt,
1617 "packet": hex.EncodeToString(packet.Data),
1618 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001619
npujarec5762e2020-01-01 14:08:48 +05301620 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001621 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001622 }
1623 } else {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001624 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1625 "egress_port_no": egressPortNo,
1626 "egressPortType": egressPortType,
1627 "packet": hex.EncodeToString(packet.Data),
1628 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001629 }
1630 return nil
1631}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001632
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001633func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1634 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001635}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301636
1637func startHeartbeatCheck(dh *DeviceHandler) {
1638 // start the heartbeat check towards the OLT.
1639 var timerCheck *time.Timer
1640
1641 for {
1642 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1643 select {
1644 case <-heartbeatTimer.C:
1645 ctx, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1646 if heartBeat, err := dh.Client.HeartbeatCheck(ctx, new(oop.Empty)); err != nil {
1647 log.Error("Hearbeat failed")
1648 if timerCheck == nil {
1649 // start a after func, when expired will update the state to the core
1650 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, dh.updateStateUnreachable)
1651 }
1652 } else {
1653 if timerCheck != nil {
1654 if timerCheck.Stop() {
1655 log.Debug("We got hearbeat within the timeout")
1656 } else {
1657
1658 log.Debug("We got hearbeat after the timeout expired, changing the states")
1659 go dh.notifyChildDevices("up")
npujarec5762e2020-01-01 14:08:48 +05301660 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301661 voltha.OperStatus_ACTIVE); err != nil {
1662 log.Errorw("Failed to update device state", log.Fields{"deviceID": dh.device.Id, "error": err})
1663 }
1664 }
1665 timerCheck = nil
1666 }
1667 log.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
1668 }
1669 cancel()
1670 case <-dh.stopHeartbeatCheck:
1671 log.Debug("Stopping heart beat check")
1672 return
1673 }
1674 }
1675}
1676
1677func (dh *DeviceHandler) updateStateUnreachable() {
1678
1679 go dh.notifyChildDevices("unreachable")
1680 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 +05301681 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301682 }
1683}
kesavand39e0aa32020-01-28 20:58:50 -05001684
1685// EnablePort to enable Pon interface
1686func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
1687 log.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001688 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001689}
1690
1691// DisablePort to disable pon interface
1692func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
1693 log.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001694 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001695}
1696
kdarapu1afeceb2020-02-12 01:38:09 -05001697//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1698func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301699 ctx := context.Background()
kdarapu1afeceb2020-02-12 01:38:09 -05001700 log.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort})
kesavand39e0aa32020-01-28 20:58:50 -05001701 if port.GetType() == voltha.Port_ETHERNET_NNI {
1702 // Bug is opened for VOL-2505 to support NNI disable feature.
1703 log.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
1704 log.Fields{"Device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301705 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001706 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001707 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001708 }
1709 // fetch interfaceid from PortNo
1710 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1711 ponIntf := &oop.Interface{IntfId: ponID}
1712 var operStatus voltha.OperStatus_Types
1713 if enablePort {
1714 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301715 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001716
1717 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301718 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001719 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001720 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001721 }
1722 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001723 dh.activePorts.Store(ponID, true)
kesavand39e0aa32020-01-28 20:58:50 -05001724 log.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1725 } else {
1726 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301727 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001728 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301729 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001730 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001731 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001732 }
1733 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001734 dh.activePorts.Store(ponID, false)
kesavand39e0aa32020-01-28 20:58:50 -05001735 log.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1736 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001737 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 +05301738 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001739 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001740 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001741 }
1742 return nil
1743}
1744
kdarapu1afeceb2020-02-12 01:38:09 -05001745//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1746func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001747 cloned := proto.Clone(device).(*voltha.Device)
1748 // Disable the port and update the oper_port_status to core
1749 // if the Admin state of the port is disabled on reboot and re-enable device.
1750 for _, port := range cloned.Ports {
1751 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001752 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301753 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001754 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001755 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001756 }
1757 }
1758 }
1759 return nil
1760}
1761
1762//populateActivePorts to populate activePorts map
1763func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
1764 log.Info("populateActiveports", log.Fields{"Device": device})
1765 for _, port := range device.Ports {
1766 if port.Type == voltha.Port_ETHERNET_NNI {
1767 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001768 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001769 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001770 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001771 }
1772 }
1773 if port.Type == voltha.Port_PON_OLT {
1774 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001775 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001776 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001777 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001778 }
1779 }
1780 }
1781}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001782
1783// ChildDeviceLost deletes ONU and clears pon resources related to it.
1784func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
1785 log.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
1786 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1787 onuKey := dh.formOnuKey(IntfID, onuID)
1788 onuDevice, ok := dh.onus.Load(onuKey)
1789 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301790 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001791 log.Fields{
1792 "device-id": dh.deviceID,
1793 "onu-id": onuID,
1794 "interface-id": IntfID}, nil).Log()
1795 }
1796 var sn *oop.SerialNumber
1797 var err error
1798 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301799 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001800 log.Fields{
1801 "devicer-id": dh.deviceID,
1802 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
1803 }
1804 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
1805 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301806 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001807 "device-id": dh.deviceID,
1808 "onu-id": onuID}, err).Log()
1809 }
1810 //clear PON resources associated with ONU
1811 var onuGemData []rsrcMgr.OnuGemInfo
1812 if err := dh.resourceMgr.ResourceMgrs[IntfID].GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001813 log.Warnw("Failed-to-get-onu-info-for-pon-port ", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001814 "device-id": dh.deviceID,
1815 "interface-id": IntfID,
1816 "error": err})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001817 } else {
1818 for i, onu := range onuGemData {
1819 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
1820 log.Debugw("onu-data ", log.Fields{"onu": onu})
1821 if err := dh.clearUNIData(ctx, &onu); err != nil {
1822 log.Warnw("Failed-to-clear-uni-data-for-onu", log.Fields{
1823 "device-id": dh.deviceID,
1824 "onu-device": onu,
1825 "error": err})
1826 }
1827 // Clear flowids for gem cache.
1828 for _, gem := range onu.GemPorts {
1829 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
1830 }
1831 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
1832 dh.resourceMgr.UpdateOnuGemInfo(ctx, IntfID, onuGemData)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001833
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001834 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
1835 break
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001836 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001837 }
1838 }
1839 dh.onus.Delete(onuKey)
1840 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
1841 return nil
1842}