blob: 625ab6368183b306f2a7136e4deb8ec7b3649526 [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{}
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +053093 losRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070094}
95
Naga Manjunath7615e552019-10-11 22:35:47 +053096var pmNames = []string{
97 "rx_bytes",
98 "rx_packets",
99 "rx_mcast_packets",
100 "rx_bcast_packets",
101 "tx_bytes",
102 "tx_packets",
103 "tx_mcast_packets",
104 "tx_bcast_packets",
105}
106
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700107//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530108func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700109 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700111 device.deviceType = deviceTp
112 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 device.onuID = onuID
114 device.intfID = intfID
115 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000116 device.uniPorts = make(map[uint32]struct{})
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530117 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700118 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530119}
120
121//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530122func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700123 var dh DeviceHandler
124 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400125 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400126 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700127 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700128 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700129 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400130 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700131 dh.device = cloned
132 dh.openOLT = adapter
133 dh.exitChannel = make(chan int, 1)
134 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530135 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530136 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530137 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 -0500138 dh.activePorts = sync.Map{}
cuilin20187b2a8c32019-03-26 19:52:28 -0700139 //TODO initialize the support classes.
140 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530141}
142
143// start save the device to the data model
144func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700145 dh.lockDevice.Lock()
146 defer dh.lockDevice.Unlock()
147 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
148 // Add the initial device to the local model
149 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530150}
151
152// stop stops the device dh. Not much to do for now
153func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700154 dh.lockDevice.Lock()
155 defer dh.lockDevice.Unlock()
156 log.Debug("stopping-device-agent")
157 dh.exitChannel <- 1
158 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530159}
160
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400161func macifyIP(ip net.IP) string {
162 if len(ip) > 0 {
163 oct1 := strconv.FormatInt(int64(ip[12]), 16)
164 oct2 := strconv.FormatInt(int64(ip[13]), 16)
165 oct3 := strconv.FormatInt(int64(ip[14]), 16)
166 oct4 := strconv.FormatInt(int64(ip[15]), 16)
167 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
168 }
169 return ""
170}
171
172func generateMacFromHost(host string) (string, error) {
173 var genmac string
174 var addr net.IP
175 var ips []string
176 var err error
177
178 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
179
180 if addr = net.ParseIP(host); addr == nil {
181 log.Debugw("looking-up-hostname", log.Fields{"host": host})
182
183 if ips, err = net.LookupHost(host); err == nil {
184 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
185 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000186 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400187 }
188 genmac = macifyIP(addr)
189 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
190 return genmac, nil
191 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000192 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400193 }
194
195 genmac = macifyIP(addr)
196 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
197 return genmac, nil
198}
199
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530200func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700201 slist := strings.Split(mac, ":")
202 result := make([]uint32, len(slist))
203 var err error
204 var tmp int64
205 for index, val := range slist {
206 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
207 return []uint32{1, 2, 3, 4, 5, 6}
208 }
209 result[index] = uint32(tmp)
210 }
211 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530212}
213
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700214//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 -0800215func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530216
David K. Bainbridge794735f2020-02-11 21:01:37 -0800217 switch portType {
218 case voltha.Port_ETHERNET_NNI:
219 return fmt.Sprintf("nni-%d", portNum), nil
220 case voltha.Port_PON_OLT:
221 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700222 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800223
Girish Kumarf26e4882020-03-05 06:49:10 +0000224 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530225}
226
David K. Bainbridge794735f2020-02-11 21:01:37 -0800227func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000228 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700229 if state == "up" {
230 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500231 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500232 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700233 } else {
234 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500235 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700236 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700237 portNum := IntfIDToPortNo(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800238 label, err := GetportLabel(portNum, portType)
239 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000240 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400241 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500242
243 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
244 if err != nil || device == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000245 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500246 }
247 if device.Ports != nil {
248 for _, dPort := range device.Ports {
249 if dPort.Type == portType && dPort.PortNo == portNum {
250 log.Debug("port-already-exists-updating-oper-status-of-port")
251 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530252 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800253 "device-id": dh.device.Id,
254 "port-type": portType,
255 "port-number": portNum,
Girish Kumarf26e4882020-03-05 06:49:10 +0000256 "oper-status": operStatus}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800257
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500258 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800259 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500260 }
261 }
262 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400263 // Now create Port
264 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700265 PortNo: portNum,
266 Label: label,
267 Type: portType,
268 OperStatus: operStatus,
269 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500270 log.Debugw("Sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700271 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700272 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000273 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800274 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000275 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400276 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800277 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530278}
279
280// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800281func (dh *DeviceHandler) readIndications(ctx context.Context) error {
282 defer log.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530283 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700284 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000285 return olterrors.NewErrCommunication("fail-to-read-indications", log.Fields{"device-id": dh.device.Id}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700286 }
287 if indications == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000288 return olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700289 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400290 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530291 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400292 if err != nil || device == nil {
293 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000294 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400295 }
296 // When the device is in DISABLED and Adapter container restarts, we need to
297 // rebuild the locally maintained admin state.
298 if device.AdminState == voltha.AdminState_DISABLED {
299 dh.lockDevice.Lock()
300 dh.adminState = "down"
301 dh.lockDevice.Unlock()
302 }
303
David Bainbridgef5879ca2019-12-13 21:17:54 +0000304 // Create an exponential backoff around re-enabling indications. The
305 // maximum elapsed time for the back off is set to 0 so that we will
306 // continue to retry. The max interval defaults to 1m, but is set
307 // here for code clarity
308 indicationBackoff := backoff.NewExponentialBackOff()
309 indicationBackoff.MaxElapsedTime = 0
310 indicationBackoff.MaxInterval = 1 * time.Minute
cuilin20187b2a8c32019-03-26 19:52:28 -0700311 for {
312 indication, err := indications.Recv()
313 if err == io.EOF {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530314 log.Infow("EOF for indications", log.Fields{"err": err})
David Bainbridgef5879ca2019-12-13 21:17:54 +0000315 // Use an exponential back off to prevent getting into a tight loop
316 duration := indicationBackoff.NextBackOff()
317 if duration == backoff.Stop {
318 // If we reach a maximum then warn and reset the backoff
319 // timer and keep attempting.
320 log.Warnw("Maximum indication backoff reached, resetting backoff timer",
321 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
322 indicationBackoff.Reset()
323 }
324 time.Sleep(indicationBackoff.NextBackOff())
npujarec5762e2020-01-01 14:08:48 +0530325 indications, err = dh.Client.EnableIndication(ctx, new(oop.Empty))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530326 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000327 return olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530328 }
329 continue
cuilin20187b2a8c32019-03-26 19:52:28 -0700330 }
331 if err != nil {
332 log.Infow("Failed to read from indications", log.Fields{"err": err})
Devmalya Paul495b94a2019-08-27 19:42:00 -0400333 if dh.adminState == "deleted" {
334 log.Debug("Device deleted stoping the read indication thread")
335 break
336 }
npujarec5762e2020-01-01 14:08:48 +0530337 dh.transitionMap.Handle(ctx, DeviceDownInd)
338 dh.transitionMap.Handle(ctx, DeviceInit)
Girish Kumarf26e4882020-03-05 06:49:10 +0000339 return olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700340 }
David Bainbridgef5879ca2019-12-13 21:17:54 +0000341 // Reset backoff if we have a successful receive
342 indicationBackoff.Reset()
Chaitrashree G S44124192019-08-07 20:21:36 -0400343 dh.lockDevice.RLock()
344 adminState := dh.adminState
345 dh.lockDevice.RUnlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400346 // When OLT is admin down, ignore all indications.
Chaitrashree G S44124192019-08-07 20:21:36 -0400347 if adminState == "down" {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530348
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +0530349 log.Infow("olt is admin down, ignore indication", log.Fields{"indication": indication})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400350 continue
351 }
npujarec5762e2020-01-01 14:08:48 +0530352 dh.handleIndication(ctx, indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530353
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700354 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800355 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700356}
357
David K. Bainbridge794735f2020-02-11 21:01:37 -0800358func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000359 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000360 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530361 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700362 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530363 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700364 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000365 // Send or clear Alarm
David K. Bainbridge794735f2020-02-11 21:01:37 -0800366 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530367 return olterrors.NewErrAdapter("failed-indication", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800368 "device_id": dh.deviceID,
369 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000370 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800371 }
372 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700373}
374
David K. Bainbridge794735f2020-02-11 21:01:37 -0800375// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530376func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400377 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700378 switch indication.Data.(type) {
379 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800380 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530381 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800382 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700383 case *oop.Indication_IntfInd:
384 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800385 go func() {
386 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530387 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800388 }
389 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700390 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
391 case *oop.Indication_IntfOperInd:
392 intfOperInd := indication.GetIntfOperInd()
393 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800394 go func() {
395 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530396 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800397 }
398 }()
npujarec5762e2020-01-01 14:08:48 +0530399 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700400 } else if intfOperInd.GetType() == "pon" {
401 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
402 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800403 go func() {
404 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530405 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800406 }
407 }()
kesavand39e0aa32020-01-28 20:58:50 -0500408 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700409 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700410 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
411 case *oop.Indication_OnuDiscInd:
412 onuDiscInd := indication.GetOnuDiscInd()
413 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700414 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800415 go func() {
416 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530417 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800418 }
419 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700420 case *oop.Indication_OnuInd:
421 onuInd := indication.GetOnuInd()
422 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800423 go func() {
424 if err := dh.onuIndication(onuInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530425 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800426 }
427 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700428 case *oop.Indication_OmciInd:
429 omciInd := indication.GetOmciInd()
lcuie24ef182019-04-29 22:58:36 -0700430 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 -0800431 go func() {
432 if err := dh.omciIndication(omciInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530433 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800434 }
435 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700436 case *oop.Indication_PktInd:
437 pktInd := indication.GetPktInd()
438 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800439 go func() {
440 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530441 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800442 }
443 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700444 case *oop.Indication_PortStats:
445 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530446 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700447 case *oop.Indication_FlowStats:
448 flowStats := indication.GetFlowStats()
449 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
450 case *oop.Indication_AlarmInd:
451 alarmInd := indication.GetAlarmInd()
452 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530453 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700454 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530455}
456
457// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530458func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400459 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530460 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400461 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000462 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400463 }
464 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530465}
466
467// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530468func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700469 dh.lockDevice.Lock()
470 defer dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400471 log.Debug("do-state-down-start")
472
npujarec5762e2020-01-01 14:08:48 +0530473 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400474 if err != nil || device == nil {
475 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000476 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400477 }
478
479 cloned := proto.Clone(device).(*voltha.Device)
480 // Update the all ports state on that device to disable
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 if err = dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000482 return olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400483 }
484
485 //Update the device oper state and connection status
486 cloned.OperStatus = voltha.OperStatus_UNKNOWN
487 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
488 dh.device = cloned
489
David K. Bainbridge794735f2020-02-11 21:01:37 -0800490 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000491 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400492 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400493
494 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530495 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400496 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000497 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400498 }
499 for _, onuDevice := range onuDevices.Items {
500
501 // Update onu state as down in onu adapter
502 onuInd := oop.OnuIndication{}
503 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800504 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700505 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800506 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530507 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800508 "source": "openolt",
509 "onu-indicator": onuInd,
510 "device-type": onuDevice.Type,
511 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700512 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700513 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400514 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700515 /* Discovered ONUs entries need to be cleared , since after OLT
516 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530517 dh.discOnus = sync.Map{}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800518 log.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700519 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530520}
521
522// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530523func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400524 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800525 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530526 return olterrors.NewErrCommunication("dial-failure", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800527 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000528 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400529 }
530 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530531}
532
533// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530534func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400535 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530536 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400537 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530538}
539
540// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530541func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400542 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400543
544 // Case where OLT is disabled and then rebooted.
545 if dh.adminState == "down" {
546 log.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530547 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400548 if err != nil || device == nil {
549 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530550 olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400551 }
552
553 cloned := proto.Clone(device).(*voltha.Device)
554 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
555 cloned.OperStatus = voltha.OperStatus_UNKNOWN
556 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530557 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530558 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400559 }
560
Chaitrashree G S44124192019-08-07 20:21:36 -0400561 // 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 +0530562 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400563 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530564 olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400565 }
566
567 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800568 go func() {
569 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530570 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800571 }
572 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400573 return nil
574 }
575
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400576 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700577 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000578 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700579 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400580
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700581 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400582 if err != nil || device == nil {
583 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000584 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400585 }
kesavand39e0aa32020-01-28 20:58:50 -0500586 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500587 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000588 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400589 }
590
Girish Gowdru0c588b22019-04-23 23:24:56 -0400591 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
592 // Instantiate resource manager
npujarec5762e2020-01-01 14:08:48 +0530593 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 +0000594 return olterrors.ErrResourceManagerInstantiating
Girish Gowdru0c588b22019-04-23 23:24:56 -0400595 }
596 // Instantiate flow manager
npujarec5762e2020-01-01 14:08:48 +0530597 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000598 return olterrors.ErrResourceManagerInstantiating
Girish Gowdru0c588b22019-04-23 23:24:56 -0400599 }
600 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400601 /* Instantiating Event Manager to handle Alarms and KPIs */
Devmalya Paul90ca3012019-09-02 21:55:45 -0400602 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
Naga Manjunath7615e552019-10-11 22:35:47 +0530603 // Stats config for new device
604 dh.portStats = NewOpenOltStatsMgr(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530605
cuilin20187b2a8c32019-03-26 19:52:28 -0700606 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800607 go func() {
608 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530609 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800610 }
611 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700612 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530613}
614
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400615func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
616 var err error
617 var deviceInfo *oop.DeviceInfo
618
619 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
620
621 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000622 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400623 }
624 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000625 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400626 }
627
628 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
629 dh.device.Root = true
630 dh.device.Vendor = deviceInfo.Vendor
631 dh.device.Model = deviceInfo.Model
632 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
633 dh.device.HardwareVersion = deviceInfo.HardwareVersion
634 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
635
636 if deviceInfo.DeviceId == "" {
637 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
638 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
639 genmac, err := generateMacFromHost(host)
640 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000641 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400642 }
643 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
644 dh.device.MacAddress = genmac
645 } else {
646 dh.device.MacAddress = deviceInfo.DeviceId
647 }
648
649 // Synchronous call to update device - this method is run in its own go routine
650 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000651 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400652 }
653
654 return deviceInfo, nil
655}
656
Naga Manjunath7615e552019-10-11 22:35:47 +0530657func startCollector(dh *DeviceHandler) {
658 // Initial delay for OLT initialization
659 time.Sleep(1 * time.Minute)
660 log.Debugf("Starting-Collector")
661 context := make(map[string]string)
662 for {
663 select {
664 case <-dh.stopCollector:
665 log.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
666 return
667 default:
668 freq := dh.metrics.ToPmConfigs().DefaultFreq
669 time.Sleep(time.Duration(freq) * time.Second)
670 context["oltid"] = dh.deviceID
671 context["devicetype"] = dh.deviceType
672 // NNI Stats
673 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
674 log.Debugf("Collect-NNI-Metrics %v", cmnni)
675 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
676 log.Debugf("Publish-NNI-Metrics")
677 // PON Stats
678 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
Chaitrashree G Sef088112020-02-03 21:39:27 -0500679 for i := uint32(0); i < NumPonPORTS; i++ {
680 if val, ok := dh.activePorts.Load(i); ok && val == true {
681 cmpon := dh.portStats.collectPONMetrics(i)
682 log.Debugf("Collect-PON-Metrics %v", cmpon)
Naga Manjunath7615e552019-10-11 22:35:47 +0530683
Chaitrashree G Sef088112020-02-03 21:39:27 -0500684 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
685 log.Debugf("Publish-PON-Metrics")
686 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530687 }
688 }
689 }
690}
691
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700692//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530693func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400694 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700695 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530696 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530697
698 // Now, set the initial PM configuration for that device
699 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530700 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530701 }
702
703 go startCollector(dh)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530704 go startHeartbeatCheck(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530705}
706
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700707//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530708func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700709 return &ic.SwitchCapability{
710 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530711 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700712 HwDesc: "open_pon",
713 SwDesc: "open_pon",
714 SerialNum: dh.device.SerialNumber,
715 },
716 SwitchFeatures: &of.OfpSwitchFeatures{
717 NBuffers: 256,
718 NTables: 2,
719 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
720 of.OfpCapabilities_OFPC_TABLE_STATS |
721 of.OfpCapabilities_OFPC_PORT_STATS |
722 of.OfpCapabilities_OFPC_GROUP_STATS),
723 },
724 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530725}
726
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700727//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530728func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700729 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700730 return &ic.PortCapability{
731 Port: &voltha.LogicalPort{
732 OfpPort: &of.OfpPort{
733 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
734 Config: 0,
735 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700736 Curr: capacity,
737 Advertised: capacity,
738 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700739 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
740 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
741 },
742 DeviceId: dh.device.Id,
743 DevicePortNo: uint32(portNo),
744 },
745 }, nil
746}
747
David K. Bainbridge794735f2020-02-11 21:01:37 -0800748func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700749 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700750 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700751 var deviceID string
752 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700753
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700754 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530755
756 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
757
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700758 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
759 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700760 kwargs := make(map[string]interface{})
761 kwargs["onu_id"] = omciInd.OnuId
762 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700763
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700764 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
765 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530766 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800767 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000768 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700769 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700770 deviceType = onuDevice.Type
771 deviceID = onuDevice.Id
772 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
773 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530774 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700775 } else {
776 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700777 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530778 deviceType = onuInCache.(*OnuDevice).deviceType
779 deviceID = onuInCache.(*OnuDevice).deviceID
780 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700781 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700782
783 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800784 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700785 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800786 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530787 return olterrors.NewErrCommunication("omci-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800788 "source": dh.deviceType,
789 "destination": deviceType,
790 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000791 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700792 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800793 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530794}
795
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700796//ProcessInterAdapterMessage sends the proxied messages to the target device
797// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
798// is meant, and then send the unmarshalled omci message to this onu
799func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
800 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700801 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700802 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700803 fromTopic := msg.Header.FromTopic
804 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700805 toDeviceID := msg.Header.ToDeviceId
806 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700807
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700808 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700809
810 msgBody := msg.GetBody()
811
812 omciMsg := &ic.InterAdapterOmciMessage{}
813 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000814 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700815 }
816
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700817 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700818 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
819 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530820 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800821 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000822 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700823 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700824 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 -0800825 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530826 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800827 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000828 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800829 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700830 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700831 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 -0800832 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530833 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800834 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000835 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800836 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700837 }
838
839 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000840 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700841 }
842 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530843}
844
David K. Bainbridge794735f2020-02-11 21:01:37 -0800845func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700846 var intfID uint32
847 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000848 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700849 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700850 intfID = onuDevice.ProxyAddress.GetChannelId()
851 onuID = onuDevice.ProxyAddress.GetOnuId()
852 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700853 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700854 intfID = omciMsg.GetProxyAddress().GetChannelId()
855 onuID = omciMsg.GetProxyAddress().GetOnuId()
856 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700857 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700858 if connectStatus != voltha.ConnectStatus_REACHABLE {
859 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800860
Thomas Lee S94109f12020-03-03 16:39:29 +0530861 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800862 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000863 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700864 }
865
lcuie24ef182019-04-29 22:58:36 -0700866 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
867 isHexString := false
868 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
869 if decodeerr == nil {
870 isHexString = true
871 }
872
873 // 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.
874 var omciMessage *oop.OmciMsg
875 if isHexString {
876 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
877 } else {
878 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
879 hex.Encode(hexPkt, omciMsg.Message)
880 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
881 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700882
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700883 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
884 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530885 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800886 "interface-id": intfID,
887 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000888 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700889 }
lcuie24ef182019-04-29 22:58:36 -0700890 log.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800891 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700892}
893
David K. Bainbridge794735f2020-02-11 21:01:37 -0800894func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700895 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
npujarec5762e2020-01-01 14:08:48 +0530896 dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700897 // TODO: need resource manager
898 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700899 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +0530900 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400901 st, _ := status.FromError(err)
902 if st.Code() == codes.AlreadyExists {
903 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
904 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000905 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400906 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700907 } else {
908 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
909 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800910 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700911}
912
David K. Bainbridge794735f2020-02-11 21:01:37 -0800913func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800914
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700915 channelID := onuDiscInd.GetIntfId()
916 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400917
Matteo Scandolo945e4012019-12-12 14:16:11 -0800918 log.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530919
cuilin20187b2a8c32019-03-26 19:52:28 -0700920 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400921 if sn != "" {
922 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400923 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000924 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400925 }
926
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530927 var alarmInd oop.OnuAlarmIndication
928 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +0000929 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530930
931 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
932 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
933 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
934 OnuLosRaise event sent for it */
935 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
936 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
937 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
938 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
939 "previousIntfId": onuInCache.(*OnuDevice).intfID,
940 "currentIntfId": onuDiscInd.GetIntfId()})
941 // TODO:: Should we need to ignore raising OnuLosClear event
942 // when onu connected to different PON?
943 }
944 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
945 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
946 alarmInd.LosStatus = statusCheckOff
947 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
948 }
949 return true
950 })
951
Amit Ghoshe5c6a852020-02-10 15:09:46 +0000952 log.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800953 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +0000954 }
955
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400956 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -0800957
958 // check the ONU is already know to the OLT
959 // NOTE the second time the ONU is discovered this should return a device
960 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
961
962 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800963 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 -0800964 if e, ok := status.FromError(err); ok {
965 log.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
966 switch e.Code() {
967 case codes.Internal:
968 // this probably means NOT FOUND, so just create a new device
969 onuDevice = nil
970 case codes.DeadlineExceeded:
971 // if the call times out, cleanup and exit
972 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +0000973 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -0800974 }
975 }
976 }
977
978 if onuDevice == nil {
979 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
980 log.Infow("creating-new-onu", log.Fields{"sn": sn})
981 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -0400982 ponintfid := onuDiscInd.GetIntfId()
983 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +0530984 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -0400985 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400986
Matteo Scandolo945e4012019-12-12 14:16:11 -0800987 log.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
988
989 if err != nil {
990 // if we can't create an ID in resource manager,
991 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -0800992 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +0000993 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800994 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +0000995 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -0800996 }
997
998 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
999 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001000 dh.discOnus.Delete(sn)
1001 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 +05301002 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001003 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001004 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001005 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -05001006 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Matteo Scandolo945e4012019-12-12 14:16:11 -08001007 log.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001008 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001009
1010 // we can now use the existing ONU Id
1011 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001012 //Insert the ONU into cache to use in OnuIndication.
1013 //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 -08001014 log.Debugw("onu-discovery-indication-key-create", log.Fields{"onuID": onuID,
1015 "intfId": onuDiscInd.GetIntfId(), "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001016 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001017
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301018 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301019 dh.onus.Store(onuKey, onuDev)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001020 log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001021
David K. Bainbridge794735f2020-02-11 21:01:37 -08001022 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301023 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001024 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001025 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001026 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001027 log.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001028 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301029 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001030 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001031 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001032 }
1033 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001034}
1035
David K. Bainbridge794735f2020-02-11 21:01:37 -08001036func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001037 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1038
1039 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001040 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001041 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001042 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001043 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -07001044 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
1045 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001046 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301047
David K. Bainbridge794735f2020-02-11 21:01:37 -08001048 errFields := log.Fields{"device-id": dh.device.Id}
1049
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301050 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1051
Mahir Gunyele77977b2019-06-27 05:36:22 -07001052 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1053 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001054 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1055 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001056 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001057 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1058 if serialNumber != "" {
1059 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001060 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001061 } else {
1062 kwargs["onu_id"] = onuInd.OnuId
1063 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001064 errFields["onu-id"] = onuInd.OnuId
1065 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001066 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001067 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001068 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001069
David K. Bainbridge794735f2020-02-11 21:01:37 -08001070 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001071 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001072 }
1073
David K. Bainbridge794735f2020-02-11 21:01:37 -08001074 if onuDevice.ParentPortNo != ponPort {
1075 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
1076 "previousIntfId": onuDevice.ParentPortNo,
1077 "currentIntfId": ponPort})
1078 }
1079
1080 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
1081 log.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
1082 "expected_onu_id": onuDevice.ProxyAddress.OnuId,
1083 "received_onu_id": onuInd.OnuId})
1084 }
1085 if !foundInCache {
1086 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1087
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301088 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001089
1090 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001091 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001092 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001093 }
1094 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001095}
1096
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001097func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301098 ctx := context.TODO()
Matt Jeanneret53539512019-07-20 14:47:02 -04001099 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 +00001100 if onuInd.AdminState == "down" {
1101 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1102 if onuInd.OperState != "down" {
1103 log.Warnw("ONU-admin-state-down", log.Fields{"operState": onuInd.OperState})
1104 onuInd.OperState = "down"
1105 }
1106 }
1107
David K. Bainbridge794735f2020-02-11 21:01:37 -08001108 switch onuInd.OperState {
1109 case "down":
Matt Jeanneret53539512019-07-20 14:47:02 -04001110 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 -07001111 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301112 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001113 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1114 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301115 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001116 "onu-indicator": onuInd,
1117 "source": "openolt",
1118 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001119 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001120 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001121 case "up":
Matt Jeanneret53539512019-07-20 14:47:02 -04001122 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
1123 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301124 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001125 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1126 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301127 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001128 "onu-indicator": onuInd,
1129 "source": "openolt",
1130 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001131 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001132 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001133 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001134 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001135 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001136 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001137}
1138
cuilin20187b2a8c32019-03-26 19:52:28 -07001139func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1140 if serialNum != nil {
1141 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001142 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001143 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001144}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001145func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1146 decodedStr, err := hex.DecodeString(serialNum[4:])
1147 if err != nil {
1148 return nil, err
1149 }
1150 return &oop.SerialNumber{
1151 VendorId: []byte(serialNum[:4]),
1152 VendorSpecific: []byte(decodedStr),
1153 }, nil
1154}
cuilin20187b2a8c32019-03-26 19:52:28 -07001155
1156func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1157 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001158 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001159 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1160 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1161 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1162 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1163 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1164 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1165 return tmp
1166}
1167
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001168//UpdateFlowsBulk upates the bulk flow
1169func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301170 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001171}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001172
1173//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001174func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001175 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001176 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001177 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001178 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001179 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001180 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001181 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001182 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001183 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001184 }
1185 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001186 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301187}
1188
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001189// SendPacketInToCore sends packet-in to core
1190// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1191// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001192func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001193 log.Debugw("send-packet-in-to-core", log.Fields{
1194 "port": logicalPort,
1195 "packet": hex.EncodeToString(packetPayload),
1196 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001197 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301198 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001199 "source": "adapter",
1200 "destination": "core",
1201 "device-id": dh.device.Id,
1202 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001203 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001204 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001205 log.Debugw("Sent packet-in to core successfully", log.Fields{
1206 "packet": hex.EncodeToString(packetPayload),
1207 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001208 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001209}
1210
A R Karthick1f85b802019-10-11 05:06:05 +00001211// AddUniPortToOnu adds the uni port to the onu device
1212func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1213 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301214
1215 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001216 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301217 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1218 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001219 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1220 }
1221 }
1222}
1223
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001224//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301225func (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 -04001226 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 +01001227
1228 var errorsList []error
1229
Girish Gowdru0c588b22019-04-23 23:24:56 -04001230 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001231 for _, flow := range flows.ToRemove.Items {
1232 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
npujarec5762e2020-01-01 14:08:48 +05301233 dh.flowMgr.RemoveFlow(ctx, flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001234 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301235
1236 for _, flow := range flows.ToAdd.Items {
1237 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001238 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1239 if err != nil {
1240 errorsList = append(errorsList, err)
1241 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301242 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001243 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001244 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001245 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001246 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001247 // dh.flowMgr.RemoveFlow(flow)
1248 }
1249 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001250
1251 if groups != nil {
1252 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001253 err := dh.flowMgr.AddGroup(ctx, group)
1254 if err != nil {
1255 errorsList = append(errorsList, err)
1256 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001257 }
1258 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001259 err := dh.flowMgr.ModifyGroup(ctx, group)
1260 if err != nil {
1261 errorsList = append(errorsList, err)
1262 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001263 }
1264 if len(groups.ToRemove.Items) != 0 {
1265 log.Debug("Group delete operation is not supported for now")
1266 }
1267 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001268 if len(errorsList) > 0 {
1269 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1270 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001271 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001272 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301273}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001274
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001275//DisableDevice disables the given device
1276//It marks the following for the given device:
1277//Device-Handler Admin-State : down
1278//Device Port-State: UNKNOWN
1279//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001280func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001281 /* On device disable ,admin state update has to be done prior sending request to agent since
1282 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001283 dh.lockDevice.Lock()
1284 dh.adminState = "down"
1285 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001286 if dh.Client != nil {
1287 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1288 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001289 dh.lockDevice.Lock()
1290 dh.adminState = "up"
1291 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001292 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001293 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001294 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001295 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001296 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001297 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001298 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301299
1300 dh.discOnus = sync.Map{}
1301 dh.onus = sync.Map{}
1302
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301303 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001304 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001305 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1306 for _, port := range cloned.Ports {
1307 if port.GetType() == voltha.Port_PON_OLT {
1308 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1309 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001310 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001311 }
1312 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001313 }
1314
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001315 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001316 return nil
1317}
1318
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301319func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001320
1321 // Update onu state as unreachable in onu adapter
1322 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301323 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001324 //get the child device for the parent device
1325 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1326 if err != nil {
1327 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1328 }
1329 if onuDevices != nil {
1330 for _, onuDevice := range onuDevices.Items {
1331 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1332 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1333 if err != nil {
1334 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1335 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1336 }
1337
1338 }
1339 }
1340
1341}
1342
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001343//ReenableDevice re-enables the olt device after disable
1344//It marks the following for the given device:
1345//Device-Handler Admin-State : up
1346//Device Port-State: ACTIVE
1347//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001348func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001349 dh.lockDevice.Lock()
1350 dh.adminState = "up"
1351 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301352
1353 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1354 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301355 dh.lockDevice.Lock()
1356 dh.adminState = "down"
1357 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001358 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301359 }
1360 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001361 log.Debug("olt-reenabled")
1362
1363 cloned := proto.Clone(device).(*voltha.Device)
1364 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001365
kdarapu1afeceb2020-02-12 01:38:09 -05001366 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001367 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001368 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001369 //Update the device oper status as ACTIVE
1370 cloned.OperStatus = voltha.OperStatus_ACTIVE
1371 dh.device = cloned
1372
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001373 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301374 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001375 "device-id": device.Id,
1376 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001377 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001378 }
kesavand39e0aa32020-01-28 20:58:50 -05001379
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001380 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001381
1382 return nil
1383}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001384
npujarec5762e2020-01-01 14:08:48 +05301385func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001386 var uniID uint32
1387 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301388 for _, port := range onu.UniPorts {
1389 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001390 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1391 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301392 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301393 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001394 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301395 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301396 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001397 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301398 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001399 }
npujarec5762e2020-01-01 14:08:48 +05301400 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001401 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301402 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301403 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001404 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301405 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301406 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301407 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001408 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301409 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1410 }
npujarec5762e2020-01-01 14:08:48 +05301411 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1412 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301413 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1414 }
1415 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301416 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301417 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 +00001418 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001419 }
1420 return nil
1421}
1422
npujarec5762e2020-01-01 14:08:48 +05301423func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001424 nniUniID := -1
1425 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301426
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001427 if dh.resourceMgr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001428 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.deviceID}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001429 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001430 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301431 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301432 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001433 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001434 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301435 log.Debugw("NNI are ", log.Fields{"nni": nni})
1436 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301437 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301438 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1439 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301440 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301441 }
npujarec5762e2020-01-01 14:08:48 +05301442 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001443 }
npujarec5762e2020-01-01 14:08:48 +05301444 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001445 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301446 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001447 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001448}
1449
1450// 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 +05301451func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001452 log.Debug("Function entry delete device")
1453 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001454 if dh.adminState == "deleted" {
1455 dh.lockDevice.Unlock()
1456 return nil
1457 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001458 dh.adminState = "deleted"
1459 dh.lockDevice.Unlock()
1460 /* Clear the KV store data associated with the all the UNI ports
1461 This clears up flow data and also resource map data for various
1462 other pon resources like alloc_id and gemport_id
1463 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001464 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301465 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1466 var ponPort uint32
1467 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1468 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301469 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301470 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301471 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001472 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001473 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301474 }
1475 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301476 onuID := make([]uint32, 1)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301477 log.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301478 if err = dh.clearUNIData(ctx, &onu); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301479 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1480 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301481 // Clear flowids for gem cache.
1482 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301483 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301484 }
1485 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301486 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301487 }
npujarec5762e2020-01-01 14:08:48 +05301488 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301489 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301490 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301491 if err != nil {
1492 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001493 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001494 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001495 /* Clear the flows from KV store associated with NNI port.
1496 There are mostly trap rules from NNI port (like LLDP)
1497 */
npujarec5762e2020-01-01 14:08:48 +05301498 if err := dh.clearNNIData(ctx); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301499 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001500 }
A R Karthick1f85b802019-10-11 05:06:05 +00001501
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001502 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301503 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001504 }
A R Karthick1f85b802019-10-11 05:06:05 +00001505
Devmalya Paul495b94a2019-08-27 19:42:00 -04001506 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301507 dh.onus.Range(func(key interface{}, value interface{}) bool {
1508 dh.onus.Delete(key)
1509 return true
1510 })
1511
Devmalya Paul495b94a2019-08-27 19:42:00 -04001512 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301513 // Stop the Stats collector
1514 dh.stopCollector <- true
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301515 // stop the heartbeat check routine
1516 dh.stopHeartbeatCheck <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001517 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001518 if dh.Client != nil {
npujarec5762e2020-01-01 14:08:48 +05301519 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001520 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001521 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001522 }
1523 cloned := proto.Clone(device).(*voltha.Device)
1524 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1525 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
npujarec5762e2020-01-01 14:08:48 +05301526 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301527 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001528 "device-id": device.Id,
1529 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001530 "oper-status": cloned.OperStatus}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001531 }
1532 return nil
1533}
1534
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001535//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001536func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1537 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001538 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001539 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001540 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001541 return nil
1542}
1543
David K. Bainbridge794735f2020-02-11 21:01:37 -08001544func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001545 log.Debugw("Received packet-in", log.Fields{
1546 "packet-indication": *packetIn,
1547 "packet": hex.EncodeToString(packetIn.Pkt),
1548 })
npujarec5762e2020-01-01 14:08:48 +05301549 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001550 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001551 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001552 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001553 log.Debugw("sending packet-in to core", log.Fields{
1554 "logicalPortNum": logicalPortNum,
1555 "packet": hex.EncodeToString(packetIn.Pkt),
1556 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001557 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301558 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001559 "destination": "core",
1560 "source": dh.deviceType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001561 "packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001562 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001563 log.Debugw("Success sending packet-in to core!", log.Fields{
1564 "packet": hex.EncodeToString(packetIn.Pkt),
1565 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001566 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001567}
1568
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001569// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301570func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001571 log.Debugw("incoming-packet-out", log.Fields{
1572 "deviceID": dh.deviceID,
1573 "egress_port_no": egressPortNo,
1574 "pkt-length": len(packet.Data),
1575 "packet": hex.EncodeToString(packet.Data),
1576 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001577
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001578 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001579 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001580 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1581 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301582 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1583 // Do not packet-out lldp packets on uni port.
1584 // ONOS has no clue about uni/nni ports, it just packets out on all
1585 // available ports on the Logical Switch. It should not be interested
1586 // in the UNI links.
1587 log.Debug("dropping-lldp-packet-out-on-uni")
1588 return nil
1589 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001590 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1591 if innerEthType == 0x8100 {
1592 // q-in-q 802.1ad or 802.1q double tagged packet.
1593 // slice out the outer tag.
1594 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1595 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001596 }
1597 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001598 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1599 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001600 uniID := UniIDFromPortNum(uint32(egressPortNo))
1601
npujarec5762e2020-01-01 14:08:48 +05301602 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001603 if err != nil {
1604 // In this case the openolt agent will receive the gemPortID as 0.
1605 // The agent tries to retrieve the gemPortID in this case.
1606 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001607 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1608 "packet": hex.EncodeToString(packet.Data),
1609 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001610 }
1611
1612 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001613
Matteo Scandolo6056e822019-11-13 14:05:29 -08001614 log.Debugw("sending-packet-to-onu", log.Fields{
1615 "egress_port_no": egressPortNo,
1616 "IntfId": intfID,
1617 "onuID": onuID,
1618 "uniID": uniID,
1619 "gemPortID": gemPortID,
1620 "packet": hex.EncodeToString(packet.Data),
1621 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001622
npujarec5762e2020-01-01 14:08:48 +05301623 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301624 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001625 "source": "adapter",
1626 "destination": "onu",
1627 "egress-port-number": egressPortNo,
1628 "interface-id": intfID,
1629 "oni-id": onuID,
1630 "uni-id": uniID,
1631 "gem-port-id": gemPortID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001632 "packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001633 }
1634 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001635 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1636 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001637 return olterrors.NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001638 }
1639 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001640
Matteo Scandolo6056e822019-11-13 14:05:29 -08001641 log.Debugw("sending-packet-to-nni", log.Fields{
1642 "uplink_pkt": uplinkPkt,
1643 "packet": hex.EncodeToString(packet.Data),
1644 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001645
npujarec5762e2020-01-01 14:08:48 +05301646 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001647 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001648 }
1649 } else {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001650 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1651 "egress_port_no": egressPortNo,
1652 "egressPortType": egressPortType,
1653 "packet": hex.EncodeToString(packet.Data),
1654 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001655 }
1656 return nil
1657}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001658
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001659func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1660 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001661}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301662
1663func startHeartbeatCheck(dh *DeviceHandler) {
1664 // start the heartbeat check towards the OLT.
1665 var timerCheck *time.Timer
1666
1667 for {
1668 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1669 select {
1670 case <-heartbeatTimer.C:
1671 ctx, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1672 if heartBeat, err := dh.Client.HeartbeatCheck(ctx, new(oop.Empty)); err != nil {
1673 log.Error("Hearbeat failed")
1674 if timerCheck == nil {
1675 // start a after func, when expired will update the state to the core
1676 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, dh.updateStateUnreachable)
1677 }
1678 } else {
1679 if timerCheck != nil {
1680 if timerCheck.Stop() {
1681 log.Debug("We got hearbeat within the timeout")
1682 } else {
1683
1684 log.Debug("We got hearbeat after the timeout expired, changing the states")
1685 go dh.notifyChildDevices("up")
npujarec5762e2020-01-01 14:08:48 +05301686 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301687 voltha.OperStatus_ACTIVE); err != nil {
1688 log.Errorw("Failed to update device state", log.Fields{"deviceID": dh.device.Id, "error": err})
1689 }
1690 }
1691 timerCheck = nil
1692 }
1693 log.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
1694 }
1695 cancel()
1696 case <-dh.stopHeartbeatCheck:
1697 log.Debug("Stopping heart beat check")
1698 return
1699 }
1700 }
1701}
1702
1703func (dh *DeviceHandler) updateStateUnreachable() {
1704
1705 go dh.notifyChildDevices("unreachable")
1706 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 +05301707 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301708 }
1709}
kesavand39e0aa32020-01-28 20:58:50 -05001710
1711// EnablePort to enable Pon interface
1712func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
1713 log.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001714 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001715}
1716
1717// DisablePort to disable pon interface
1718func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
1719 log.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001720 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001721}
1722
kdarapu1afeceb2020-02-12 01:38:09 -05001723//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1724func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301725 ctx := context.Background()
kdarapu1afeceb2020-02-12 01:38:09 -05001726 log.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort})
kesavand39e0aa32020-01-28 20:58:50 -05001727 if port.GetType() == voltha.Port_ETHERNET_NNI {
1728 // Bug is opened for VOL-2505 to support NNI disable feature.
1729 log.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
1730 log.Fields{"Device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301731 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001732 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001733 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001734 }
1735 // fetch interfaceid from PortNo
1736 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1737 ponIntf := &oop.Interface{IntfId: ponID}
1738 var operStatus voltha.OperStatus_Types
1739 if enablePort {
1740 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301741 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001742
1743 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301744 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001745 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001746 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001747 }
1748 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001749 dh.activePorts.Store(ponID, true)
kesavand39e0aa32020-01-28 20:58:50 -05001750 log.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1751 } else {
1752 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301753 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001754 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301755 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001756 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001757 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001758 }
1759 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001760 dh.activePorts.Store(ponID, false)
kesavand39e0aa32020-01-28 20:58:50 -05001761 log.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1762 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001763 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 +05301764 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001765 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001766 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001767 }
1768 return nil
1769}
1770
kdarapu1afeceb2020-02-12 01:38:09 -05001771//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1772func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001773 cloned := proto.Clone(device).(*voltha.Device)
1774 // Disable the port and update the oper_port_status to core
1775 // if the Admin state of the port is disabled on reboot and re-enable device.
1776 for _, port := range cloned.Ports {
1777 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001778 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301779 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001780 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001781 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001782 }
1783 }
1784 }
1785 return nil
1786}
1787
1788//populateActivePorts to populate activePorts map
1789func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
1790 log.Info("populateActiveports", log.Fields{"Device": device})
1791 for _, port := range device.Ports {
1792 if port.Type == voltha.Port_ETHERNET_NNI {
1793 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001794 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001795 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001796 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001797 }
1798 }
1799 if port.Type == voltha.Port_PON_OLT {
1800 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001801 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001802 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001803 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001804 }
1805 }
1806 }
1807}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001808
1809// ChildDeviceLost deletes ONU and clears pon resources related to it.
1810func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
1811 log.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
1812 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1813 onuKey := dh.formOnuKey(IntfID, onuID)
1814 onuDevice, ok := dh.onus.Load(onuKey)
1815 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301816 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001817 log.Fields{
1818 "device-id": dh.deviceID,
1819 "onu-id": onuID,
1820 "interface-id": IntfID}, nil).Log()
1821 }
1822 var sn *oop.SerialNumber
1823 var err error
1824 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301825 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001826 log.Fields{
1827 "devicer-id": dh.deviceID,
1828 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
1829 }
1830 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
1831 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301832 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001833 "device-id": dh.deviceID,
1834 "onu-id": onuID}, err).Log()
1835 }
1836 //clear PON resources associated with ONU
1837 var onuGemData []rsrcMgr.OnuGemInfo
1838 if err := dh.resourceMgr.ResourceMgrs[IntfID].GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001839 log.Warnw("Failed-to-get-onu-info-for-pon-port ", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001840 "device-id": dh.deviceID,
1841 "interface-id": IntfID,
1842 "error": err})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001843 } else {
1844 for i, onu := range onuGemData {
1845 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
1846 log.Debugw("onu-data ", log.Fields{"onu": onu})
1847 if err := dh.clearUNIData(ctx, &onu); err != nil {
1848 log.Warnw("Failed-to-clear-uni-data-for-onu", log.Fields{
1849 "device-id": dh.deviceID,
1850 "onu-device": onu,
1851 "error": err})
1852 }
1853 // Clear flowids for gem cache.
1854 for _, gem := range onu.GemPorts {
1855 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
1856 }
1857 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
1858 dh.resourceMgr.UpdateOnuGemInfo(ctx, IntfID, onuGemData)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001859
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001860 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
1861 break
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001862 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001863 }
1864 }
1865 dh.onus.Delete(onuKey)
1866 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
1867 return nil
1868}