blob: 2b0b52a3529d6d9db2b7e9768132da5270d74016 [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
Chaitrashree G Sa4649252020-03-11 21:24:11 -040082 stopIndications chan bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070083}
84
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070085//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070086type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070088 deviceType string
89 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070090 onuID uint32
91 intfID uint32
92 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +000093 uniPorts map[uint32]struct{}
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +053094 losRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070095}
96
Naga Manjunath7615e552019-10-11 22:35:47 +053097var pmNames = []string{
98 "rx_bytes",
99 "rx_packets",
100 "rx_mcast_packets",
101 "rx_bcast_packets",
102 "tx_bytes",
103 "tx_packets",
104 "tx_mcast_packets",
105 "tx_bcast_packets",
106}
107
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700108//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530109func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700110 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700112 device.deviceType = deviceTp
113 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 device.onuID = onuID
115 device.intfID = intfID
116 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000117 device.uniPorts = make(map[uint32]struct{})
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530118 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700119 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530120}
121
122//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530123func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700124 var dh DeviceHandler
125 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400126 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400127 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700128 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700129 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700130 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400131 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700132 dh.device = cloned
133 dh.openOLT = adapter
134 dh.exitChannel = make(chan int, 1)
135 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530136 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530137 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530138 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 -0500139 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400140 dh.stopIndications = make(chan bool, 1)
cuilin20187b2a8c32019-03-26 19:52:28 -0700141 //TODO initialize the support classes.
142 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530143}
144
145// start save the device to the data model
146func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700147 dh.lockDevice.Lock()
148 defer dh.lockDevice.Unlock()
149 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
150 // Add the initial device to the local model
151 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530152}
153
154// stop stops the device dh. Not much to do for now
155func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700156 dh.lockDevice.Lock()
157 defer dh.lockDevice.Unlock()
158 log.Debug("stopping-device-agent")
159 dh.exitChannel <- 1
160 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530161}
162
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400163func macifyIP(ip net.IP) string {
164 if len(ip) > 0 {
165 oct1 := strconv.FormatInt(int64(ip[12]), 16)
166 oct2 := strconv.FormatInt(int64(ip[13]), 16)
167 oct3 := strconv.FormatInt(int64(ip[14]), 16)
168 oct4 := strconv.FormatInt(int64(ip[15]), 16)
169 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
170 }
171 return ""
172}
173
174func generateMacFromHost(host string) (string, error) {
175 var genmac string
176 var addr net.IP
177 var ips []string
178 var err error
179
180 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
181
182 if addr = net.ParseIP(host); addr == nil {
183 log.Debugw("looking-up-hostname", log.Fields{"host": host})
184
185 if ips, err = net.LookupHost(host); err == nil {
186 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
187 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000188 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400189 }
190 genmac = macifyIP(addr)
191 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
192 return genmac, nil
193 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000194 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400195 }
196
197 genmac = macifyIP(addr)
198 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
199 return genmac, nil
200}
201
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530202func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700203 slist := strings.Split(mac, ":")
204 result := make([]uint32, len(slist))
205 var err error
206 var tmp int64
207 for index, val := range slist {
208 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
209 return []uint32{1, 2, 3, 4, 5, 6}
210 }
211 result[index] = uint32(tmp)
212 }
213 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530214}
215
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700216//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 -0800217func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530218
David K. Bainbridge794735f2020-02-11 21:01:37 -0800219 switch portType {
220 case voltha.Port_ETHERNET_NNI:
221 return fmt.Sprintf("nni-%d", portNum), nil
222 case voltha.Port_PON_OLT:
223 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700224 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800225
Girish Kumarf26e4882020-03-05 06:49:10 +0000226 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530227}
228
David K. Bainbridge794735f2020-02-11 21:01:37 -0800229func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000230 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700231 if state == "up" {
232 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500233 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500234 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700235 } else {
236 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500237 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700238 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700239 portNum := IntfIDToPortNo(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800240 label, err := GetportLabel(portNum, portType)
241 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000242 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400243 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500244
245 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
246 if err != nil || device == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000247 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500248 }
249 if device.Ports != nil {
250 for _, dPort := range device.Ports {
251 if dPort.Type == portType && dPort.PortNo == portNum {
252 log.Debug("port-already-exists-updating-oper-status-of-port")
253 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530254 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800255 "device-id": dh.device.Id,
256 "port-type": portType,
257 "port-number": portNum,
Girish Kumarf26e4882020-03-05 06:49:10 +0000258 "oper-status": operStatus}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800259
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500260 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800261 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500262 }
263 }
264 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400265 // Now create Port
266 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700267 PortNo: portNum,
268 Label: label,
269 Type: portType,
270 OperStatus: operStatus,
271 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500272 log.Debugw("Sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700273 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700274 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000275 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800276 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000277 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400278 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800279 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530280}
281
282// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800283func (dh *DeviceHandler) readIndications(ctx context.Context) error {
284 defer log.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530285 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700286 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000287 return olterrors.NewErrCommunication("fail-to-read-indications", log.Fields{"device-id": dh.device.Id}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700288 }
289 if indications == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000290 return olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700291 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400292 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530293 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400294 if err != nil || device == nil {
295 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000296 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400297 }
298 // When the device is in DISABLED and Adapter container restarts, we need to
299 // rebuild the locally maintained admin state.
300 if device.AdminState == voltha.AdminState_DISABLED {
301 dh.lockDevice.Lock()
302 dh.adminState = "down"
303 dh.lockDevice.Unlock()
304 }
305
David Bainbridgef5879ca2019-12-13 21:17:54 +0000306 // Create an exponential backoff around re-enabling indications. The
307 // maximum elapsed time for the back off is set to 0 so that we will
308 // continue to retry. The max interval defaults to 1m, but is set
309 // here for code clarity
310 indicationBackoff := backoff.NewExponentialBackOff()
311 indicationBackoff.MaxElapsedTime = 0
312 indicationBackoff.MaxInterval = 1 * time.Minute
cuilin20187b2a8c32019-03-26 19:52:28 -0700313 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400314 select {
315 case <-dh.stopIndications:
316 log.Debugw("Stopping-collecting-indications-for-OLT", log.Fields{"deviceID:": dh.deviceID})
317 break
318 default:
319 indication, err := indications.Recv()
320 if err == io.EOF {
321 log.Infow("EOF for indications", log.Fields{"err": err})
322 // Use an exponential back off to prevent getting into a tight loop
323 duration := indicationBackoff.NextBackOff()
324 if duration == backoff.Stop {
325 // If we reach a maximum then warn and reset the backoff
326 // timer and keep attempting.
327 log.Warnw("Maximum indication backoff reached, resetting backoff timer",
328 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
329 indicationBackoff.Reset()
330 }
331 time.Sleep(indicationBackoff.NextBackOff())
332 indications, err = dh.Client.EnableIndication(ctx, new(oop.Empty))
333 if err != nil {
334 return olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
335 }
336 if indications == nil {
337 return olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
338 }
339 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000340 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530341 if err != nil {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400342 if dh.adminState == "deleted" {
343 log.Debug("Device deleted stoping the read indication thread")
344 break
345 }
346 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530347 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400348 // Reset backoff if we have a successful receive
349 indicationBackoff.Reset()
350 dh.lockDevice.RLock()
351 adminState := dh.adminState
352 dh.lockDevice.RUnlock()
353 // When OLT is admin down, ignore all indications.
354 if adminState == "down" && !isIndicationAllowedDuringOltAdminDown(indication) {
355 log.Debugw("olt is admin down, ignore indication", log.Fields{"indication": indication})
356 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400357 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400358 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700359 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700360 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400361}
362
363// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
364func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
365 switch indication.Data.(type) {
366 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
367 return true
368
369 default:
370 return false
371 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700372}
373
David K. Bainbridge794735f2020-02-11 21:01:37 -0800374func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000375 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000376 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530377 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700378 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530379 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700380 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000381 // Send or clear Alarm
David K. Bainbridge794735f2020-02-11 21:01:37 -0800382 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530383 return olterrors.NewErrAdapter("failed-indication", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800384 "device_id": dh.deviceID,
385 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000386 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800387 }
388 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700389}
390
David K. Bainbridge794735f2020-02-11 21:01:37 -0800391// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530392func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400393 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700394 switch indication.Data.(type) {
395 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800396 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530397 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800398 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700399 case *oop.Indication_IntfInd:
400 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800401 go func() {
402 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530403 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800404 }
405 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700406 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
407 case *oop.Indication_IntfOperInd:
408 intfOperInd := indication.GetIntfOperInd()
409 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800410 go func() {
411 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530412 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800413 }
414 }()
npujarec5762e2020-01-01 14:08:48 +0530415 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700416 } else if intfOperInd.GetType() == "pon" {
417 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
418 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800419 go func() {
420 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530421 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800422 }
423 }()
kesavand39e0aa32020-01-28 20:58:50 -0500424 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700425 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700426 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
427 case *oop.Indication_OnuDiscInd:
428 onuDiscInd := indication.GetOnuDiscInd()
429 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700430 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800431 go func() {
432 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530433 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800434 }
435 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700436 case *oop.Indication_OnuInd:
437 onuInd := indication.GetOnuInd()
438 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800439 go func() {
440 if err := dh.onuIndication(onuInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530441 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800442 }
443 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700444 case *oop.Indication_OmciInd:
445 omciInd := indication.GetOmciInd()
lcuie24ef182019-04-29 22:58:36 -0700446 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 -0800447 go func() {
448 if err := dh.omciIndication(omciInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530449 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800450 }
451 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700452 case *oop.Indication_PktInd:
453 pktInd := indication.GetPktInd()
454 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800455 go func() {
456 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530457 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800458 }
459 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700460 case *oop.Indication_PortStats:
461 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530462 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700463 case *oop.Indication_FlowStats:
464 flowStats := indication.GetFlowStats()
465 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
466 case *oop.Indication_AlarmInd:
467 alarmInd := indication.GetAlarmInd()
468 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530469 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700470 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530471}
472
473// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530474func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400475 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530476 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400477 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000478 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400479 }
480 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530481}
482
483// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530484func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700485 dh.lockDevice.Lock()
486 defer dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400487 log.Debug("do-state-down-start")
488
npujarec5762e2020-01-01 14:08:48 +0530489 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400490 if err != nil || device == nil {
491 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000492 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400493 }
494
495 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400496
497 //Update the device oper state and connection status
498 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400499 dh.device = cloned
500
David K. Bainbridge794735f2020-02-11 21:01:37 -0800501 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000502 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400503 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400504
505 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530506 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400507 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000508 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400509 }
510 for _, onuDevice := range onuDevices.Items {
511
512 // Update onu state as down in onu adapter
513 onuInd := oop.OnuIndication{}
514 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800515 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700516 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800517 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530518 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800519 "source": "openolt",
520 "onu-indicator": onuInd,
521 "device-type": onuDevice.Type,
522 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700523 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700524 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400525 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700526 /* Discovered ONUs entries need to be cleared , since after OLT
527 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530528 dh.discOnus = sync.Map{}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800529 log.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700530 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530531}
532
533// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530534func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400535 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800536 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530537 return olterrors.NewErrCommunication("dial-failure", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800538 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000539 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400540 }
541 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530542}
543
544// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530545func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400546 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530547 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400548 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530549}
550
551// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530552func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400553 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400554
555 // Case where OLT is disabled and then rebooted.
556 if dh.adminState == "down" {
557 log.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530558 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400559 if err != nil || device == nil {
560 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530561 olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400562 }
563
564 cloned := proto.Clone(device).(*voltha.Device)
565 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
566 cloned.OperStatus = voltha.OperStatus_UNKNOWN
567 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530568 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530569 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400570 }
571
Chaitrashree G S44124192019-08-07 20:21:36 -0400572 // 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 +0530573 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400574 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530575 olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400576 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400577 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
578 // all the modules initialized and ready to handle incoming ONUs.
579
580 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
581 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
582 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400583
584 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800585 go func() {
586 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530587 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800588 }
589 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400590 return nil
591 }
592
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700593 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400594 if err != nil || device == nil {
595 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000596 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400597 }
kesavand39e0aa32020-01-28 20:58:50 -0500598 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500599 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000600 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400601 }
602
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400603 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
604 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400605 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530606
cuilin20187b2a8c32019-03-26 19:52:28 -0700607 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800608 go func() {
609 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530610 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800611 }
612 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700613 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530614}
615
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400616func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
617 deviceInfo, err := dh.populateDeviceInfo()
618
619 if err != nil {
620 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
621 }
622 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
623 // Instantiate resource manager
624 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
625 return olterrors.ErrResourceManagerInstantiating
626 }
627
628 // Instantiate flow manager
629 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
630 return olterrors.ErrResourceManagerInstantiating
631
632 }
633 /* TODO: Instantiate Alarm , stats , BW managers */
634 /* Instantiating Event Manager to handle Alarms and KPIs */
635 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
636
637 // Stats config for new device
638 dh.portStats = NewOpenOltStatsMgr(dh)
639
640 return nil
641
642}
643
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400644func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
645 var err error
646 var deviceInfo *oop.DeviceInfo
647
648 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
649
650 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000651 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400652 }
653 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000654 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400655 }
656
657 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
658 dh.device.Root = true
659 dh.device.Vendor = deviceInfo.Vendor
660 dh.device.Model = deviceInfo.Model
661 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
662 dh.device.HardwareVersion = deviceInfo.HardwareVersion
663 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
664
665 if deviceInfo.DeviceId == "" {
666 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
667 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
668 genmac, err := generateMacFromHost(host)
669 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000670 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400671 }
672 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
673 dh.device.MacAddress = genmac
674 } else {
675 dh.device.MacAddress = deviceInfo.DeviceId
676 }
677
678 // Synchronous call to update device - this method is run in its own go routine
679 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000680 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400681 }
682
683 return deviceInfo, nil
684}
685
Naga Manjunath7615e552019-10-11 22:35:47 +0530686func startCollector(dh *DeviceHandler) {
687 // Initial delay for OLT initialization
688 time.Sleep(1 * time.Minute)
689 log.Debugf("Starting-Collector")
690 context := make(map[string]string)
691 for {
692 select {
693 case <-dh.stopCollector:
694 log.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
695 return
696 default:
697 freq := dh.metrics.ToPmConfigs().DefaultFreq
698 time.Sleep(time.Duration(freq) * time.Second)
699 context["oltid"] = dh.deviceID
700 context["devicetype"] = dh.deviceType
701 // NNI Stats
702 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
703 log.Debugf("Collect-NNI-Metrics %v", cmnni)
704 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
705 log.Debugf("Publish-NNI-Metrics")
706 // PON Stats
707 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
Chaitrashree G Sef088112020-02-03 21:39:27 -0500708 for i := uint32(0); i < NumPonPORTS; i++ {
709 if val, ok := dh.activePorts.Load(i); ok && val == true {
710 cmpon := dh.portStats.collectPONMetrics(i)
711 log.Debugf("Collect-PON-Metrics %v", cmpon)
Naga Manjunath7615e552019-10-11 22:35:47 +0530712
Chaitrashree G Sef088112020-02-03 21:39:27 -0500713 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
714 log.Debugf("Publish-PON-Metrics")
715 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530716 }
717 }
718 }
719}
720
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700721//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530722func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400723 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700724 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530725 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530726
727 // Now, set the initial PM configuration for that device
728 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530729 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530730 }
731
732 go startCollector(dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400733 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530734}
735
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700736//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530737func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700738 return &ic.SwitchCapability{
739 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530740 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700741 HwDesc: "open_pon",
742 SwDesc: "open_pon",
743 SerialNum: dh.device.SerialNumber,
744 },
745 SwitchFeatures: &of.OfpSwitchFeatures{
746 NBuffers: 256,
747 NTables: 2,
748 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
749 of.OfpCapabilities_OFPC_TABLE_STATS |
750 of.OfpCapabilities_OFPC_PORT_STATS |
751 of.OfpCapabilities_OFPC_GROUP_STATS),
752 },
753 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530754}
755
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700756//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530757func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700758 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700759 return &ic.PortCapability{
760 Port: &voltha.LogicalPort{
761 OfpPort: &of.OfpPort{
762 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
763 Config: 0,
764 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700765 Curr: capacity,
766 Advertised: capacity,
767 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700768 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
769 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
770 },
771 DeviceId: dh.device.Id,
772 DevicePortNo: uint32(portNo),
773 },
774 }, nil
775}
776
David K. Bainbridge794735f2020-02-11 21:01:37 -0800777func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700778 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700779 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700780 var deviceID string
781 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700782
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700783 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530784
785 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
786
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700787 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
788 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700789 kwargs := make(map[string]interface{})
790 kwargs["onu_id"] = omciInd.OnuId
791 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700792
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700793 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
794 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530795 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800796 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000797 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700798 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700799 deviceType = onuDevice.Type
800 deviceID = onuDevice.Id
801 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
802 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530803 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700804 } else {
805 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700806 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530807 deviceType = onuInCache.(*OnuDevice).deviceType
808 deviceID = onuInCache.(*OnuDevice).deviceID
809 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700810 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700811
812 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800813 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700814 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800815 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530816 return olterrors.NewErrCommunication("omci-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800817 "source": dh.deviceType,
818 "destination": deviceType,
819 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000820 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700821 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800822 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530823}
824
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700825//ProcessInterAdapterMessage sends the proxied messages to the target device
826// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
827// is meant, and then send the unmarshalled omci message to this onu
828func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
829 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700830 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700831 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700832 fromTopic := msg.Header.FromTopic
833 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700834 toDeviceID := msg.Header.ToDeviceId
835 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700836
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700837 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700838
839 msgBody := msg.GetBody()
840
841 omciMsg := &ic.InterAdapterOmciMessage{}
842 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000843 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700844 }
845
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700846 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700847 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
848 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530849 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800850 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000851 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700852 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700853 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 -0800854 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530855 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800856 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000857 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800858 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700859 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700860 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 -0800861 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530862 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800863 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000864 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800865 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700866 }
867
868 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000869 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700870 }
871 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530872}
873
David K. Bainbridge794735f2020-02-11 21:01:37 -0800874func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700875 var intfID uint32
876 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000877 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700878 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700879 intfID = onuDevice.ProxyAddress.GetChannelId()
880 onuID = onuDevice.ProxyAddress.GetOnuId()
881 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700882 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700883 intfID = omciMsg.GetProxyAddress().GetChannelId()
884 onuID = omciMsg.GetProxyAddress().GetOnuId()
885 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700886 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700887 if connectStatus != voltha.ConnectStatus_REACHABLE {
888 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800889
Thomas Lee S94109f12020-03-03 16:39:29 +0530890 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800891 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000892 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700893 }
894
lcuie24ef182019-04-29 22:58:36 -0700895 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
896 isHexString := false
897 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
898 if decodeerr == nil {
899 isHexString = true
900 }
901
902 // 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.
903 var omciMessage *oop.OmciMsg
904 if isHexString {
905 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
906 } else {
907 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
908 hex.Encode(hexPkt, omciMsg.Message)
909 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
910 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700911
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700912 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
913 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530914 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800915 "interface-id": intfID,
916 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000917 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700918 }
lcuie24ef182019-04-29 22:58:36 -0700919 log.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800920 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700921}
922
David K. Bainbridge794735f2020-02-11 21:01:37 -0800923func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700924 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
npujarec5762e2020-01-01 14:08:48 +0530925 dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700926 // TODO: need resource manager
927 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700928 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +0530929 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400930 st, _ := status.FromError(err)
931 if st.Code() == codes.AlreadyExists {
932 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
933 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000934 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400935 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700936 } else {
937 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
938 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800939 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700940}
941
David K. Bainbridge794735f2020-02-11 21:01:37 -0800942func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800943
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700944 channelID := onuDiscInd.GetIntfId()
945 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400946
Matteo Scandolo945e4012019-12-12 14:16:11 -0800947 log.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530948
cuilin20187b2a8c32019-03-26 19:52:28 -0700949 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400950 if sn != "" {
951 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400952 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000953 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400954 }
955
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530956 var alarmInd oop.OnuAlarmIndication
957 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +0000958 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530959
960 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
961 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
962 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
963 OnuLosRaise event sent for it */
964 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
965 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
966 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
967 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
968 "previousIntfId": onuInCache.(*OnuDevice).intfID,
969 "currentIntfId": onuDiscInd.GetIntfId()})
970 // TODO:: Should we need to ignore raising OnuLosClear event
971 // when onu connected to different PON?
972 }
973 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
974 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
975 alarmInd.LosStatus = statusCheckOff
976 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
977 }
978 return true
979 })
980
Amit Ghoshe5c6a852020-02-10 15:09:46 +0000981 log.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800982 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +0000983 }
984
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400985 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -0800986
987 // check the ONU is already know to the OLT
988 // NOTE the second time the ONU is discovered this should return a device
989 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
990
991 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800992 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 -0800993 if e, ok := status.FromError(err); ok {
994 log.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
995 switch e.Code() {
996 case codes.Internal:
997 // this probably means NOT FOUND, so just create a new device
998 onuDevice = nil
999 case codes.DeadlineExceeded:
1000 // if the call times out, cleanup and exit
1001 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001002 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001003 }
1004 }
1005 }
1006
1007 if onuDevice == nil {
1008 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
1009 log.Infow("creating-new-onu", log.Fields{"sn": sn})
1010 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001011 ponintfid := onuDiscInd.GetIntfId()
1012 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301013 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001014 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001015
Matteo Scandolo945e4012019-12-12 14:16:11 -08001016 log.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
1017
1018 if err != nil {
1019 // if we can't create an ID in resource manager,
1020 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001021 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001022 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001023 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001024 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001025 }
1026
1027 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1028 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001029 dh.discOnus.Delete(sn)
1030 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 +05301031 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001032 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001033 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001034 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -05001035 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Matteo Scandolo945e4012019-12-12 14:16:11 -08001036 log.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001037 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001038
1039 // we can now use the existing ONU Id
1040 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001041 //Insert the ONU into cache to use in OnuIndication.
1042 //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 -08001043 log.Debugw("onu-discovery-indication-key-create", log.Fields{"onuID": onuID,
1044 "intfId": onuDiscInd.GetIntfId(), "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001045 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001046
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301047 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301048 dh.onus.Store(onuKey, onuDev)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001049 log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001050
David K. Bainbridge794735f2020-02-11 21:01:37 -08001051 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301052 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001053 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001054 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001055 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001056 log.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001057 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301058 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001059 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001060 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001061 }
1062 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001063}
1064
David K. Bainbridge794735f2020-02-11 21:01:37 -08001065func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001066 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1067
1068 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001069 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001070 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001071 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001072 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -07001073 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
1074 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001075 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301076
David K. Bainbridge794735f2020-02-11 21:01:37 -08001077 errFields := log.Fields{"device-id": dh.device.Id}
1078
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301079 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1080
Mahir Gunyele77977b2019-06-27 05:36:22 -07001081 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1082 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001083 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1084 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001085 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001086 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1087 if serialNumber != "" {
1088 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001089 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001090 } else {
1091 kwargs["onu_id"] = onuInd.OnuId
1092 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001093 errFields["onu-id"] = onuInd.OnuId
1094 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001095 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001096 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001097 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001098
David K. Bainbridge794735f2020-02-11 21:01:37 -08001099 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001100 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001101 }
1102
David K. Bainbridge794735f2020-02-11 21:01:37 -08001103 if onuDevice.ParentPortNo != ponPort {
1104 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
1105 "previousIntfId": onuDevice.ParentPortNo,
1106 "currentIntfId": ponPort})
1107 }
1108
1109 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
1110 log.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
1111 "expected_onu_id": onuDevice.ProxyAddress.OnuId,
1112 "received_onu_id": onuInd.OnuId})
1113 }
1114 if !foundInCache {
1115 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1116
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301117 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 -08001118
1119 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001120 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001121 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001122 }
1123 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001124}
1125
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001126func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301127 ctx := context.TODO()
Matt Jeanneret53539512019-07-20 14:47:02 -04001128 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 +00001129 if onuInd.AdminState == "down" {
1130 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1131 if onuInd.OperState != "down" {
1132 log.Warnw("ONU-admin-state-down", log.Fields{"operState": onuInd.OperState})
1133 onuInd.OperState = "down"
1134 }
1135 }
1136
David K. Bainbridge794735f2020-02-11 21:01:37 -08001137 switch onuInd.OperState {
1138 case "down":
Matt Jeanneret53539512019-07-20 14:47:02 -04001139 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 -07001140 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301141 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001142 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1143 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301144 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001145 "onu-indicator": onuInd,
1146 "source": "openolt",
1147 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001148 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001149 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001150 case "up":
Matt Jeanneret53539512019-07-20 14:47:02 -04001151 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
1152 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301153 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001154 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1155 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301156 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001157 "onu-indicator": onuInd,
1158 "source": "openolt",
1159 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001160 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001161 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001162 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001163 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001164 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001165 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001166}
1167
cuilin20187b2a8c32019-03-26 19:52:28 -07001168func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1169 if serialNum != nil {
1170 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001171 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001172 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001173}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001174func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1175 decodedStr, err := hex.DecodeString(serialNum[4:])
1176 if err != nil {
1177 return nil, err
1178 }
1179 return &oop.SerialNumber{
1180 VendorId: []byte(serialNum[:4]),
1181 VendorSpecific: []byte(decodedStr),
1182 }, nil
1183}
cuilin20187b2a8c32019-03-26 19:52:28 -07001184
1185func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1186 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001187 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001188 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1189 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1190 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1191 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1192 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1193 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1194 return tmp
1195}
1196
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001197//UpdateFlowsBulk upates the bulk flow
1198func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301199 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001200}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001201
1202//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001203func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001204 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001205 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001206 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001207 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001208 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001209 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001210 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001211 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001212 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001213 }
1214 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001215 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301216}
1217
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001218// SendPacketInToCore sends packet-in to core
1219// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1220// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001221func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001222 log.Debugw("send-packet-in-to-core", log.Fields{
1223 "port": logicalPort,
1224 "packet": hex.EncodeToString(packetPayload),
1225 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001226 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301227 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001228 "source": "adapter",
1229 "destination": "core",
1230 "device-id": dh.device.Id,
1231 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001232 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001233 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001234 log.Debugw("Sent packet-in to core successfully", log.Fields{
1235 "packet": hex.EncodeToString(packetPayload),
1236 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001237 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001238}
1239
A R Karthick1f85b802019-10-11 05:06:05 +00001240// AddUniPortToOnu adds the uni port to the onu device
1241func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1242 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301243
1244 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001245 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301246 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1247 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001248 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1249 }
1250 }
1251}
1252
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001253//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301254func (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 -04001255 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 +01001256
1257 var errorsList []error
1258
Girish Gowdru0c588b22019-04-23 23:24:56 -04001259 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001260 for _, flow := range flows.ToRemove.Items {
1261 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
npujarec5762e2020-01-01 14:08:48 +05301262 dh.flowMgr.RemoveFlow(ctx, flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001263 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301264
1265 for _, flow := range flows.ToAdd.Items {
1266 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001267 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1268 if err != nil {
1269 errorsList = append(errorsList, err)
1270 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301271 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001272 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001273 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001274 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001275 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001276 // dh.flowMgr.RemoveFlow(flow)
1277 }
1278 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001279
1280 if groups != nil {
1281 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001282 err := dh.flowMgr.AddGroup(ctx, group)
1283 if err != nil {
1284 errorsList = append(errorsList, err)
1285 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001286 }
1287 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001288 err := dh.flowMgr.ModifyGroup(ctx, group)
1289 if err != nil {
1290 errorsList = append(errorsList, err)
1291 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001292 }
1293 if len(groups.ToRemove.Items) != 0 {
1294 log.Debug("Group delete operation is not supported for now")
1295 }
1296 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001297 if len(errorsList) > 0 {
1298 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1299 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001300 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001301 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301302}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001303
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001304//DisableDevice disables the given device
1305//It marks the following for the given device:
1306//Device-Handler Admin-State : down
1307//Device Port-State: UNKNOWN
1308//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001309func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001310 /* On device disable ,admin state update has to be done prior sending request to agent since
1311 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001312 dh.lockDevice.Lock()
1313 dh.adminState = "down"
1314 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001315 if dh.Client != nil {
1316 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1317 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001318 dh.lockDevice.Lock()
1319 dh.adminState = "up"
1320 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001321 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001322 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001323 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001324 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001325 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001326 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001327 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301328
1329 dh.discOnus = sync.Map{}
1330 dh.onus = sync.Map{}
1331
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301332 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001333 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001334 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1335 for _, port := range cloned.Ports {
1336 if port.GetType() == voltha.Port_PON_OLT {
1337 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1338 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001339 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001340 }
1341 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001342 }
1343
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001344 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001345 return nil
1346}
1347
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301348func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001349
1350 // Update onu state as unreachable in onu adapter
1351 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301352 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001353 //get the child device for the parent device
1354 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1355 if err != nil {
1356 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1357 }
1358 if onuDevices != nil {
1359 for _, onuDevice := range onuDevices.Items {
1360 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1361 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1362 if err != nil {
1363 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1364 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1365 }
1366
1367 }
1368 }
1369
1370}
1371
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001372//ReenableDevice re-enables the olt device after disable
1373//It marks the following for the given device:
1374//Device-Handler Admin-State : up
1375//Device Port-State: ACTIVE
1376//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001377func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001378 dh.lockDevice.Lock()
1379 dh.adminState = "up"
1380 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301381
1382 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1383 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301384 dh.lockDevice.Lock()
1385 dh.adminState = "down"
1386 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001387 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301388 }
1389 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001390 log.Debug("olt-reenabled")
1391
1392 cloned := proto.Clone(device).(*voltha.Device)
1393 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001394
kdarapu1afeceb2020-02-12 01:38:09 -05001395 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001396 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001397 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001398 //Update the device oper status as ACTIVE
1399 cloned.OperStatus = voltha.OperStatus_ACTIVE
1400 dh.device = cloned
1401
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001402 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301403 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001404 "device-id": device.Id,
1405 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001406 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001407 }
kesavand39e0aa32020-01-28 20:58:50 -05001408
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001409 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001410
1411 return nil
1412}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001413
npujarec5762e2020-01-01 14:08:48 +05301414func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001415 var uniID uint32
1416 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301417 for _, port := range onu.UniPorts {
1418 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001419 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1420 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301421 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301422 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001423 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301424 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301425 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001426 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301427 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001428 }
npujarec5762e2020-01-01 14:08:48 +05301429 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001430 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301431 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301432 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001433 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301434 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301435 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301436 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001437 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301438 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1439 }
npujarec5762e2020-01-01 14:08:48 +05301440 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1441 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301442 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1443 }
1444 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301445 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301446 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 +00001447 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001448 }
1449 return nil
1450}
1451
npujarec5762e2020-01-01 14:08:48 +05301452func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001453 nniUniID := -1
1454 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301455
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001456 if dh.resourceMgr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001457 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.deviceID}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001458 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001459 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301460 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301461 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001462 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001463 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301464 log.Debugw("NNI are ", log.Fields{"nni": nni})
1465 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301466 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301467 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1468 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301469 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301470 }
npujarec5762e2020-01-01 14:08:48 +05301471 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001472 }
npujarec5762e2020-01-01 14:08:48 +05301473 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001474 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301475 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001476 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001477}
1478
1479// 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 +05301480func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001481 log.Debug("Function entry delete device")
1482 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001483 if dh.adminState == "deleted" {
1484 dh.lockDevice.Unlock()
1485 return nil
1486 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001487 dh.adminState = "deleted"
1488 dh.lockDevice.Unlock()
1489 /* Clear the KV store data associated with the all the UNI ports
1490 This clears up flow data and also resource map data for various
1491 other pon resources like alloc_id and gemport_id
1492 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001493 go dh.cleanupDeviceResources(ctx)
1494 log.Debug("Removed-device-from-Resource-manager-KV-store")
1495 // Stop the Stats collector
1496 dh.stopCollector <- true
1497 // stop the heartbeat check routine
1498 dh.stopHeartbeatCheck <- true
1499 //Reset the state
1500 if dh.Client != nil {
1501 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
1502 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
1503 }
1504 }
1505 cloned := proto.Clone(device).(*voltha.Device)
1506 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1507 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1508 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1509 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1510 "device-id": device.Id,
1511 "connect-status": cloned.ConnectStatus,
1512 "oper-status": cloned.OperStatus}, err).Log()
1513 }
1514 return nil
1515}
1516func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001517 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301518 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1519 var ponPort uint32
1520 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1521 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301522 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301523 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301524 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001525 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001526 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301527 }
1528 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301529 onuID := make([]uint32, 1)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301530 log.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301531 if err = dh.clearUNIData(ctx, &onu); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301532 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1533 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301534 // Clear flowids for gem cache.
1535 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301536 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301537 }
1538 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301539 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301540 }
npujarec5762e2020-01-01 14:08:48 +05301541 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301542 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301543 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301544 if err != nil {
1545 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001546 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001547 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001548 /* Clear the flows from KV store associated with NNI port.
1549 There are mostly trap rules from NNI port (like LLDP)
1550 */
npujarec5762e2020-01-01 14:08:48 +05301551 if err := dh.clearNNIData(ctx); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301552 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001553 }
A R Karthick1f85b802019-10-11 05:06:05 +00001554
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001555 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301556 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001557 }
A R Karthick1f85b802019-10-11 05:06:05 +00001558
Devmalya Paul495b94a2019-08-27 19:42:00 -04001559 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301560 dh.onus.Range(func(key interface{}, value interface{}) bool {
1561 dh.onus.Delete(key)
1562 return true
1563 })
1564
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001565 /*Delete discovered ONU map for the device*/
1566 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1567 dh.discOnus.Delete(key)
1568 return true
1569 })
1570
Devmalya Paul495b94a2019-08-27 19:42:00 -04001571 return nil
1572}
1573
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001574//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001575func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1576 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001577 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001578 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001579 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001580 return nil
1581}
1582
David K. Bainbridge794735f2020-02-11 21:01:37 -08001583func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001584 log.Debugw("Received packet-in", log.Fields{
1585 "packet-indication": *packetIn,
1586 "packet": hex.EncodeToString(packetIn.Pkt),
1587 })
npujarec5762e2020-01-01 14:08:48 +05301588 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001589 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001590 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001591 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001592 log.Debugw("sending packet-in to core", log.Fields{
1593 "logicalPortNum": logicalPortNum,
1594 "packet": hex.EncodeToString(packetIn.Pkt),
1595 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001596 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301597 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001598 "destination": "core",
1599 "source": dh.deviceType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001600 "packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001601 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001602 log.Debugw("Success sending packet-in to core!", log.Fields{
1603 "packet": hex.EncodeToString(packetIn.Pkt),
1604 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001605 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001606}
1607
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001608// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301609func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001610 log.Debugw("incoming-packet-out", log.Fields{
1611 "deviceID": dh.deviceID,
1612 "egress_port_no": egressPortNo,
1613 "pkt-length": len(packet.Data),
1614 "packet": hex.EncodeToString(packet.Data),
1615 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001616
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001617 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001618 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001619 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1620 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301621 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1622 // Do not packet-out lldp packets on uni port.
1623 // ONOS has no clue about uni/nni ports, it just packets out on all
1624 // available ports on the Logical Switch. It should not be interested
1625 // in the UNI links.
1626 log.Debug("dropping-lldp-packet-out-on-uni")
1627 return nil
1628 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001629 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1630 if innerEthType == 0x8100 {
1631 // q-in-q 802.1ad or 802.1q double tagged packet.
1632 // slice out the outer tag.
1633 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1634 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001635 }
1636 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001637 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1638 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001639 uniID := UniIDFromPortNum(uint32(egressPortNo))
1640
npujarec5762e2020-01-01 14:08:48 +05301641 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001642 if err != nil {
1643 // In this case the openolt agent will receive the gemPortID as 0.
1644 // The agent tries to retrieve the gemPortID in this case.
1645 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001646 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1647 "packet": hex.EncodeToString(packet.Data),
1648 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001649 }
1650
1651 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001652
Matteo Scandolo6056e822019-11-13 14:05:29 -08001653 log.Debugw("sending-packet-to-onu", log.Fields{
1654 "egress_port_no": egressPortNo,
1655 "IntfId": intfID,
1656 "onuID": onuID,
1657 "uniID": uniID,
1658 "gemPortID": gemPortID,
1659 "packet": hex.EncodeToString(packet.Data),
1660 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001661
npujarec5762e2020-01-01 14:08:48 +05301662 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301663 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001664 "source": "adapter",
1665 "destination": "onu",
1666 "egress-port-number": egressPortNo,
1667 "interface-id": intfID,
1668 "oni-id": onuID,
1669 "uni-id": uniID,
1670 "gem-port-id": gemPortID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001671 "packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001672 }
1673 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001674 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1675 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001676 return olterrors.NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001677 }
1678 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001679
Matteo Scandolo6056e822019-11-13 14:05:29 -08001680 log.Debugw("sending-packet-to-nni", log.Fields{
1681 "uplink_pkt": uplinkPkt,
1682 "packet": hex.EncodeToString(packet.Data),
1683 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001684
npujarec5762e2020-01-01 14:08:48 +05301685 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001686 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001687 }
1688 } else {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001689 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1690 "egress_port_no": egressPortNo,
1691 "egressPortType": egressPortType,
1692 "packet": hex.EncodeToString(packet.Data),
1693 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001694 }
1695 return nil
1696}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001697
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001698func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1699 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001700}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301701
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001702func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301703 // start the heartbeat check towards the OLT.
1704 var timerCheck *time.Timer
1705
1706 for {
1707 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1708 select {
1709 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001710 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1711 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301712 log.Error("Hearbeat failed")
1713 if timerCheck == nil {
1714 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001715 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301716 }
1717 } else {
1718 if timerCheck != nil {
1719 if timerCheck.Stop() {
1720 log.Debug("We got hearbeat within the timeout")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301721 }
1722 timerCheck = nil
1723 }
1724 log.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
1725 }
1726 cancel()
1727 case <-dh.stopHeartbeatCheck:
1728 log.Debug("Stopping heart beat check")
1729 return
1730 }
1731 }
1732}
1733
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001734func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1735 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1736 if err != nil || device == nil {
1737 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1738 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301739
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001740 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1741 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1742 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1743 }
1744 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1745 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1746 }
1747 go dh.cleanupDeviceResources(ctx)
1748
1749 dh.stopIndications <- true
1750 dh.transitionMap.Handle(ctx, DeviceInit)
1751
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301752 }
1753}
kesavand39e0aa32020-01-28 20:58:50 -05001754
1755// EnablePort to enable Pon interface
1756func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
1757 log.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001758 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001759}
1760
1761// DisablePort to disable pon interface
1762func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
1763 log.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001764 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001765}
1766
kdarapu1afeceb2020-02-12 01:38:09 -05001767//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1768func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301769 ctx := context.Background()
kdarapu1afeceb2020-02-12 01:38:09 -05001770 log.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort})
kesavand39e0aa32020-01-28 20:58:50 -05001771 if port.GetType() == voltha.Port_ETHERNET_NNI {
1772 // Bug is opened for VOL-2505 to support NNI disable feature.
1773 log.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
1774 log.Fields{"Device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301775 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001776 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001777 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001778 }
1779 // fetch interfaceid from PortNo
1780 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1781 ponIntf := &oop.Interface{IntfId: ponID}
1782 var operStatus voltha.OperStatus_Types
1783 if enablePort {
1784 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301785 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001786
1787 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301788 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001789 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001790 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001791 }
1792 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001793 dh.activePorts.Store(ponID, true)
kesavand39e0aa32020-01-28 20:58:50 -05001794 log.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1795 } else {
1796 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301797 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001798 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301799 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001800 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001801 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001802 }
1803 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001804 dh.activePorts.Store(ponID, false)
kesavand39e0aa32020-01-28 20:58:50 -05001805 log.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1806 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001807 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 +05301808 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001809 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001810 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001811 }
1812 return nil
1813}
1814
kdarapu1afeceb2020-02-12 01:38:09 -05001815//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1816func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001817 cloned := proto.Clone(device).(*voltha.Device)
1818 // Disable the port and update the oper_port_status to core
1819 // if the Admin state of the port is disabled on reboot and re-enable device.
1820 for _, port := range cloned.Ports {
1821 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001822 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301823 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001824 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001825 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001826 }
1827 }
1828 }
1829 return nil
1830}
1831
1832//populateActivePorts to populate activePorts map
1833func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
1834 log.Info("populateActiveports", log.Fields{"Device": device})
1835 for _, port := range device.Ports {
1836 if port.Type == voltha.Port_ETHERNET_NNI {
1837 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001838 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001839 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001840 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001841 }
1842 }
1843 if port.Type == voltha.Port_PON_OLT {
1844 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001845 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001846 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001847 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001848 }
1849 }
1850 }
1851}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001852
1853// ChildDeviceLost deletes ONU and clears pon resources related to it.
1854func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
1855 log.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
1856 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1857 onuKey := dh.formOnuKey(IntfID, onuID)
1858 onuDevice, ok := dh.onus.Load(onuKey)
1859 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301860 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001861 log.Fields{
1862 "device-id": dh.deviceID,
1863 "onu-id": onuID,
1864 "interface-id": IntfID}, nil).Log()
1865 }
1866 var sn *oop.SerialNumber
1867 var err error
1868 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301869 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001870 log.Fields{
1871 "devicer-id": dh.deviceID,
1872 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
1873 }
1874 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
1875 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301876 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001877 "device-id": dh.deviceID,
1878 "onu-id": onuID}, err).Log()
1879 }
1880 //clear PON resources associated with ONU
1881 var onuGemData []rsrcMgr.OnuGemInfo
1882 if err := dh.resourceMgr.ResourceMgrs[IntfID].GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001883 log.Warnw("Failed-to-get-onu-info-for-pon-port ", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001884 "device-id": dh.deviceID,
1885 "interface-id": IntfID,
1886 "error": err})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001887 } else {
1888 for i, onu := range onuGemData {
1889 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
1890 log.Debugw("onu-data ", log.Fields{"onu": onu})
1891 if err := dh.clearUNIData(ctx, &onu); err != nil {
1892 log.Warnw("Failed-to-clear-uni-data-for-onu", log.Fields{
1893 "device-id": dh.deviceID,
1894 "onu-device": onu,
1895 "error": err})
1896 }
1897 // Clear flowids for gem cache.
1898 for _, gem := range onu.GemPorts {
1899 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
1900 }
1901 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
1902 dh.resourceMgr.UpdateOnuGemInfo(ctx, IntfID, onuGemData)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001903
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001904 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
1905 break
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001906 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001907 }
1908 }
1909 dh.onus.Delete(onuKey)
1910 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
1911 return nil
1912}