blob: 447079d202ec5c1898b82c80d1fc017d2a321589 [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
17//Package adaptercore provides the utility for olt devices, flows and statistics
Phaneendra Manda4c62c802019-03-06 21:37:49 +053018package adaptercore
19
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"
Girish Gowdru0c588b22019-04-23 23:24:56 -040039 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000040 "github.com/opencord/voltha-protos/v3/go/common"
41 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
42 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
43 oop "github.com/opencord/voltha-protos/v3/go/openolt"
44 "github.com/opencord/voltha-protos/v3/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070045 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040046 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053047)
48
salmansiddiqui7ac62132019-08-22 03:58:50 +000049// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040050const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000051 MaxRetry = 10
52 MaxTimeOutInMs = 500
Manikkaraj kb1d51442019-07-23 10:41:02 -040053)
54
Phaneendra Manda4c62c802019-03-06 21:37:49 +053055//DeviceHandler will interact with the OLT device.
56type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070057 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070058 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040059 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070060 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053061 coreProxy adapterif.CoreProxy
62 AdapterProxy adapterif.AdapterProxy
63 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070064 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070065 exitChannel chan int
66 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053067 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070068 transitionMap *TransitionMap
69 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053070 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040071 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053072 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053073
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +053074 discOnus sync.Map
75 onus sync.Map
76 portStats *OpenOltStatisticsMgr
77 metrics *pmmetrics.PmMetrics
78 stopCollector chan bool
79 stopHeartbeatCheck chan bool
Chaitrashree G Sef088112020-02-03 21:39:27 -050080 activePorts sync.Map
Mahir Gunyela3f9add2019-06-06 15:13:19 -070081}
82
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070084type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070085 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070086 deviceType string
87 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070088 onuID uint32
89 intfID uint32
90 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +000091 uniPorts map[uint32]struct{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -070092}
93
Naga Manjunath7615e552019-10-11 22:35:47 +053094var pmNames = []string{
95 "rx_bytes",
96 "rx_packets",
97 "rx_mcast_packets",
98 "rx_bcast_packets",
99 "tx_bytes",
100 "tx_packets",
101 "tx_mcast_packets",
102 "tx_bcast_packets",
103}
104
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700105//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700106func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700107 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700109 device.deviceType = deviceTp
110 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 device.onuID = onuID
112 device.intfID = intfID
113 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000114 device.uniPorts = make(map[uint32]struct{})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700115 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530116}
117
118//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530119func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700120 var dh DeviceHandler
121 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400122 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400123 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700124 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700125 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700126 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400127 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700128 dh.device = cloned
129 dh.openOLT = adapter
130 dh.exitChannel = make(chan int, 1)
131 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530132 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530133 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530134 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 -0500135 dh.activePorts = sync.Map{}
cuilin20187b2a8c32019-03-26 19:52:28 -0700136 //TODO initialize the support classes.
137 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530138}
139
140// start save the device to the data model
141func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700142 dh.lockDevice.Lock()
143 defer dh.lockDevice.Unlock()
144 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
145 // Add the initial device to the local model
146 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530147}
148
149// stop stops the device dh. Not much to do for now
150func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700151 dh.lockDevice.Lock()
152 defer dh.lockDevice.Unlock()
153 log.Debug("stopping-device-agent")
154 dh.exitChannel <- 1
155 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530156}
157
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400158func macifyIP(ip net.IP) string {
159 if len(ip) > 0 {
160 oct1 := strconv.FormatInt(int64(ip[12]), 16)
161 oct2 := strconv.FormatInt(int64(ip[13]), 16)
162 oct3 := strconv.FormatInt(int64(ip[14]), 16)
163 oct4 := strconv.FormatInt(int64(ip[15]), 16)
164 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
165 }
166 return ""
167}
168
169func generateMacFromHost(host string) (string, error) {
170 var genmac string
171 var addr net.IP
172 var ips []string
173 var err error
174
175 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
176
177 if addr = net.ParseIP(host); addr == nil {
178 log.Debugw("looking-up-hostname", log.Fields{"host": host})
179
180 if ips, err = net.LookupHost(host); err == nil {
181 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
182 if addr = net.ParseIP(ips[0]); addr == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800183 return "", NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400184 }
185 genmac = macifyIP(addr)
186 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
187 return genmac, nil
188 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800189 return "", NewErrAdapter("cannot-resolve-hostname-to-ip", nil, err).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400190 }
191
192 genmac = macifyIP(addr)
193 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
194 return genmac, nil
195}
196
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530197func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700198 slist := strings.Split(mac, ":")
199 result := make([]uint32, len(slist))
200 var err error
201 var tmp int64
202 for index, val := range slist {
203 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
204 return []uint32{1, 2, 3, 4, 5, 6}
205 }
206 result[index] = uint32(tmp)
207 }
208 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530209}
210
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700211//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 -0800212func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530213
David K. Bainbridge794735f2020-02-11 21:01:37 -0800214 switch portType {
215 case voltha.Port_ETHERNET_NNI:
216 return fmt.Sprintf("nni-%d", portNum), nil
217 case voltha.Port_PON_OLT:
218 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700219 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800220
221 return "", NewErrInvalidValue(log.Fields{"port-type": portType}, nil).Log()
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530222}
223
David K. Bainbridge794735f2020-02-11 21:01:37 -0800224func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000225 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700226 if state == "up" {
227 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500228 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500229 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700230 } else {
231 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500232 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700233 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700234 portNum := IntfIDToPortNo(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800235 label, err := GetportLabel(portNum, portType)
236 if err != nil {
237 return NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, nil).Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -0400238 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500239
240 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
241 if err != nil || device == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800242 return NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500243 }
244 if device.Ports != nil {
245 for _, dPort := range device.Ports {
246 if dPort.Type == portType && dPort.PortNo == portNum {
247 log.Debug("port-already-exists-updating-oper-status-of-port")
248 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800249 return NewErrAdapter("failed-to-update-port-state", log.Fields{
250 "device-id": dh.device.Id,
251 "port-type": portType,
252 "port-number": portNum,
253 "oper-status": operStatus}, err).Log()
254
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500255 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800256 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500257 }
258 }
259 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400260 // Now create Port
261 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700262 PortNo: portNum,
263 Label: label,
264 Type: portType,
265 OperStatus: operStatus,
266 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500267 log.Debugw("Sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700268 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700269 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800270 return NewErrAdapter("Error-creating-port", log.Fields{
271 "device-id": dh.device.Id,
272 "port-type": portType}, err).Log()
Girish Gowdru1110ef22019-06-24 11:17:59 -0400273 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800274 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530275}
276
277// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800278func (dh *DeviceHandler) readIndications(ctx context.Context) error {
279 defer log.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530280 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700281 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800282 return NewErrCommunication("fail-to-read-indications", log.Fields{"device-id": dh.device.Id}, err).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700283 }
284 if indications == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800285 return NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700286 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400287 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530288 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400289 if err != nil || device == nil {
290 /*TODO: needs to handle error scenarios */
David K. Bainbridge794735f2020-02-11 21:01:37 -0800291 return NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400292 }
293 // When the device is in DISABLED and Adapter container restarts, we need to
294 // rebuild the locally maintained admin state.
295 if device.AdminState == voltha.AdminState_DISABLED {
296 dh.lockDevice.Lock()
297 dh.adminState = "down"
298 dh.lockDevice.Unlock()
299 }
300
David Bainbridgef5879ca2019-12-13 21:17:54 +0000301 // Create an exponential backoff around re-enabling indications. The
302 // maximum elapsed time for the back off is set to 0 so that we will
303 // continue to retry. The max interval defaults to 1m, but is set
304 // here for code clarity
305 indicationBackoff := backoff.NewExponentialBackOff()
306 indicationBackoff.MaxElapsedTime = 0
307 indicationBackoff.MaxInterval = 1 * time.Minute
cuilin20187b2a8c32019-03-26 19:52:28 -0700308 for {
309 indication, err := indications.Recv()
310 if err == io.EOF {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530311 log.Infow("EOF for indications", log.Fields{"err": err})
David Bainbridgef5879ca2019-12-13 21:17:54 +0000312 // Use an exponential back off to prevent getting into a tight loop
313 duration := indicationBackoff.NextBackOff()
314 if duration == backoff.Stop {
315 // If we reach a maximum then warn and reset the backoff
316 // timer and keep attempting.
317 log.Warnw("Maximum indication backoff reached, resetting backoff timer",
318 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
319 indicationBackoff.Reset()
320 }
321 time.Sleep(indicationBackoff.NextBackOff())
npujarec5762e2020-01-01 14:08:48 +0530322 indications, err = dh.Client.EnableIndication(ctx, new(oop.Empty))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530323 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800324 return NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530325 }
326 continue
cuilin20187b2a8c32019-03-26 19:52:28 -0700327 }
328 if err != nil {
329 log.Infow("Failed to read from indications", log.Fields{"err": err})
Devmalya Paul495b94a2019-08-27 19:42:00 -0400330 if dh.adminState == "deleted" {
331 log.Debug("Device deleted stoping the read indication thread")
332 break
333 }
npujarec5762e2020-01-01 14:08:48 +0530334 dh.transitionMap.Handle(ctx, DeviceDownInd)
335 dh.transitionMap.Handle(ctx, DeviceInit)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800336 return NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700337 }
David Bainbridgef5879ca2019-12-13 21:17:54 +0000338 // Reset backoff if we have a successful receive
339 indicationBackoff.Reset()
Chaitrashree G S44124192019-08-07 20:21:36 -0400340 dh.lockDevice.RLock()
341 adminState := dh.adminState
342 dh.lockDevice.RUnlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400343 // When OLT is admin down, ignore all indications.
Chaitrashree G S44124192019-08-07 20:21:36 -0400344 if adminState == "down" {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530345
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +0530346 log.Infow("olt is admin down, ignore indication", log.Fields{"indication": indication})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400347 continue
348 }
npujarec5762e2020-01-01 14:08:48 +0530349 dh.handleIndication(ctx, indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530350
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700351 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800352 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700353}
354
David K. Bainbridge794735f2020-02-11 21:01:37 -0800355func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000356 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000357 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530358 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700359 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530360 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700361 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000362 // Send or clear Alarm
David K. Bainbridge794735f2020-02-11 21:01:37 -0800363 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs); err != nil {
364 return NewErrAdapter("failed-indication", log.Fields{
365 "device_id": dh.deviceID,
366 "indication": oltIndication,
367 "timestamp": raisedTs}, err).Log()
368 }
369 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700370}
371
David K. Bainbridge794735f2020-02-11 21:01:37 -0800372// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530373func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400374 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700375 switch indication.Data.(type) {
376 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800377 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
378 NewErrAdapter("handle-indication-error", log.Fields{"type": "olt"}, err).Log()
379 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700380 case *oop.Indication_IntfInd:
381 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800382 go func() {
383 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
384 NewErrAdapter("handle-indication-error", log.Fields{"type": "interface"}, err).Log()
385 }
386 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700387 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
388 case *oop.Indication_IntfOperInd:
389 intfOperInd := indication.GetIntfOperInd()
390 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800391 go func() {
392 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
393 NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni"}, err).Log()
394 }
395 }()
npujarec5762e2020-01-01 14:08:48 +0530396 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700397 } else if intfOperInd.GetType() == "pon" {
398 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
399 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800400 go func() {
401 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
402 NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon"}, err).Log()
403 }
404 }()
kesavand39e0aa32020-01-28 20:58:50 -0500405 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700406 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700407 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
408 case *oop.Indication_OnuDiscInd:
409 onuDiscInd := indication.GetOnuDiscInd()
410 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700411 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800412 go func() {
413 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
414 NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery"}, err).Log()
415 }
416 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700417 case *oop.Indication_OnuInd:
418 onuInd := indication.GetOnuInd()
419 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800420 go func() {
421 if err := dh.onuIndication(onuInd); err != nil {
422 NewErrAdapter("handle-indication-error", log.Fields{"type": "onu"}, err).Log()
423 }
424 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700425 case *oop.Indication_OmciInd:
426 omciInd := indication.GetOmciInd()
lcuie24ef182019-04-29 22:58:36 -0700427 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 -0800428 go func() {
429 if err := dh.omciIndication(omciInd); err != nil {
430 NewErrAdapter("handle-indication-error", log.Fields{"type": "omci"}, err).Log()
431 }
432 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700433 case *oop.Indication_PktInd:
434 pktInd := indication.GetPktInd()
435 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800436 go func() {
437 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
438 NewErrAdapter("handle-indication-error", log.Fields{"type": "packet"}, err).Log()
439 }
440 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700441 case *oop.Indication_PortStats:
442 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530443 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700444 case *oop.Indication_FlowStats:
445 flowStats := indication.GetFlowStats()
446 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
447 case *oop.Indication_AlarmInd:
448 alarmInd := indication.GetAlarmInd()
449 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530450 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700451 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530452}
453
454// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530455func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400456 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530457 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400458 voltha.OperStatus_ACTIVE); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800459 return NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -0400460 }
461 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530462}
463
464// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530465func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700466 dh.lockDevice.Lock()
467 defer dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400468 log.Debug("do-state-down-start")
469
npujarec5762e2020-01-01 14:08:48 +0530470 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400471 if err != nil || device == nil {
472 /*TODO: needs to handle error scenarios */
David K. Bainbridge794735f2020-02-11 21:01:37 -0800473 return NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrud4245152019-05-10 00:47:31 -0400474 }
475
476 cloned := proto.Clone(device).(*voltha.Device)
477 // Update the all ports state on that device to disable
David K. Bainbridge794735f2020-02-11 21:01:37 -0800478 if err = dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
479 return NewErrAdapter("port-update-failed", log.Fields{"device-id": device.Id}, err).Log()
Girish Gowdrud4245152019-05-10 00:47:31 -0400480 }
481
482 //Update the device oper state and connection status
483 cloned.OperStatus = voltha.OperStatus_UNKNOWN
484 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
485 dh.device = cloned
486
David K. Bainbridge794735f2020-02-11 21:01:37 -0800487 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
488 return NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err).Log()
Girish Gowdrud4245152019-05-10 00:47:31 -0400489 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400490
491 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530492 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400493 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800494 return NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400495 }
496 for _, onuDevice := range onuDevices.Items {
497
498 // Update onu state as down in onu adapter
499 onuInd := oop.OnuIndication{}
500 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800501 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700502 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800503 if err != nil {
504 NewErrCommunication("inter-adapter-send-failed", log.Fields{
505 "source": "openolt",
506 "onu-indicator": onuInd,
507 "device-type": onuDevice.Type,
508 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700509 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700510 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400511 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700512 /* Discovered ONUs entries need to be cleared , since after OLT
513 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530514 dh.discOnus = sync.Map{}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800515 log.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700516 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530517}
518
519// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530520func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400521 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800522 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
523 return NewErrCommunication("dial-failure", log.Fields{
524 "device-id": dh.deviceID,
525 "host-and-port": dh.device.GetHostAndPort()}, err).Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -0400526 }
527 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530528}
529
530// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530531func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400532 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530533 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400534 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530535}
536
537// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530538func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400539 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400540
541 // Case where OLT is disabled and then rebooted.
542 if dh.adminState == "down" {
543 log.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530544 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400545 if err != nil || device == nil {
546 /*TODO: needs to handle error scenarios */
David K. Bainbridge794735f2020-02-11 21:01:37 -0800547 NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400548 }
549
550 cloned := proto.Clone(device).(*voltha.Device)
551 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
552 cloned.OperStatus = voltha.OperStatus_UNKNOWN
553 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530554 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800555 NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400556 }
557
Chaitrashree G S44124192019-08-07 20:21:36 -0400558 // 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 +0530559 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400560 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800561 NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400562 }
563
564 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800565 go func() {
566 if err := dh.readIndications(ctx); err != nil {
567 NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
568 }
569 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400570 return nil
571 }
572
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400573 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700574 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800575 return NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700576 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400577
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700578 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400579 if err != nil || device == nil {
580 /*TODO: needs to handle error scenarios */
David K. Bainbridge794735f2020-02-11 21:01:37 -0800581 return NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrud4245152019-05-10 00:47:31 -0400582 }
kesavand39e0aa32020-01-28 20:58:50 -0500583 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500584 if err := dh.disableAdminDownPorts(device); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800585 return NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err).Log()
Girish Gowdrud4245152019-05-10 00:47:31 -0400586 }
587
Girish Gowdru0c588b22019-04-23 23:24:56 -0400588 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
589 // Instantiate resource manager
npujarec5762e2020-01-01 14:08:48 +0530590 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800591 return ErrResourceManagerInstantiating.Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -0400592 }
593 // Instantiate flow manager
npujarec5762e2020-01-01 14:08:48 +0530594 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800595 return ErrResourceManagerInstantiating.Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -0400596 }
597 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400598 /* Instantiating Event Manager to handle Alarms and KPIs */
Devmalya Paul90ca3012019-09-02 21:55:45 -0400599 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
Naga Manjunath7615e552019-10-11 22:35:47 +0530600 // Stats config for new device
601 dh.portStats = NewOpenOltStatsMgr(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530602
cuilin20187b2a8c32019-03-26 19:52:28 -0700603 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800604 go func() {
605 if err := dh.readIndications(ctx); err != nil {
606 NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
607 }
608 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700609 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530610}
611
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400612func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
613 var err error
614 var deviceInfo *oop.DeviceInfo
615
616 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
617
618 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800619 return nil, NewErrPersistence("get", "device", 0, nil, err).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400620 }
621 if deviceInfo == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800622 return nil, NewErrInvalidValue(log.Fields{"device": nil}, nil).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400623 }
624
625 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
626 dh.device.Root = true
627 dh.device.Vendor = deviceInfo.Vendor
628 dh.device.Model = deviceInfo.Model
629 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
630 dh.device.HardwareVersion = deviceInfo.HardwareVersion
631 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
632
633 if deviceInfo.DeviceId == "" {
634 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
635 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
636 genmac, err := generateMacFromHost(host)
637 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800638 return nil, NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400639 }
640 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
641 dh.device.MacAddress = genmac
642 } else {
643 dh.device.MacAddress = deviceInfo.DeviceId
644 }
645
646 // Synchronous call to update device - this method is run in its own go routine
647 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800648 return nil, NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400649 }
650
651 return deviceInfo, nil
652}
653
Naga Manjunath7615e552019-10-11 22:35:47 +0530654func startCollector(dh *DeviceHandler) {
655 // Initial delay for OLT initialization
656 time.Sleep(1 * time.Minute)
657 log.Debugf("Starting-Collector")
658 context := make(map[string]string)
659 for {
660 select {
661 case <-dh.stopCollector:
662 log.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
663 return
664 default:
665 freq := dh.metrics.ToPmConfigs().DefaultFreq
666 time.Sleep(time.Duration(freq) * time.Second)
667 context["oltid"] = dh.deviceID
668 context["devicetype"] = dh.deviceType
669 // NNI Stats
670 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
671 log.Debugf("Collect-NNI-Metrics %v", cmnni)
672 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
673 log.Debugf("Publish-NNI-Metrics")
674 // PON Stats
675 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
Chaitrashree G Sef088112020-02-03 21:39:27 -0500676 for i := uint32(0); i < NumPonPORTS; i++ {
677 if val, ok := dh.activePorts.Load(i); ok && val == true {
678 cmpon := dh.portStats.collectPONMetrics(i)
679 log.Debugf("Collect-PON-Metrics %v", cmpon)
Naga Manjunath7615e552019-10-11 22:35:47 +0530680
Chaitrashree G Sef088112020-02-03 21:39:27 -0500681 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
682 log.Debugf("Publish-PON-Metrics")
683 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530684 }
685 }
686 }
687}
688
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700689//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530690func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400691 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700692 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530693 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530694
695 // Now, set the initial PM configuration for that device
696 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800697 NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530698 }
699
700 go startCollector(dh)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530701 go startHeartbeatCheck(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530702}
703
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700704//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530705func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700706 return &ic.SwitchCapability{
707 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530708 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700709 HwDesc: "open_pon",
710 SwDesc: "open_pon",
711 SerialNum: dh.device.SerialNumber,
712 },
713 SwitchFeatures: &of.OfpSwitchFeatures{
714 NBuffers: 256,
715 NTables: 2,
716 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
717 of.OfpCapabilities_OFPC_TABLE_STATS |
718 of.OfpCapabilities_OFPC_PORT_STATS |
719 of.OfpCapabilities_OFPC_GROUP_STATS),
720 },
721 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530722}
723
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700724//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530725func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700726 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700727 return &ic.PortCapability{
728 Port: &voltha.LogicalPort{
729 OfpPort: &of.OfpPort{
730 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
731 Config: 0,
732 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700733 Curr: capacity,
734 Advertised: capacity,
735 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700736 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
737 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
738 },
739 DeviceId: dh.device.Id,
740 DevicePortNo: uint32(portNo),
741 },
742 }, nil
743}
744
David K. Bainbridge794735f2020-02-11 21:01:37 -0800745func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700746 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700747 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700748 var deviceID string
749 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700750
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700751 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530752
753 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
754
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700755 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
756 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700757 kwargs := make(map[string]interface{})
758 kwargs["onu_id"] = omciInd.OnuId
759 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700760
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700761 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
762 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800763 return NewErrNotFound("onu", log.Fields{
764 "interface-id": omciInd.IntfId,
765 "onu-id": omciInd.OnuId}, err).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700766 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700767 deviceType = onuDevice.Type
768 deviceID = onuDevice.Id
769 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
770 //if not exist in cache, then add to cache.
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530771 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700772 } else {
773 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700774 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530775 deviceType = onuInCache.(*OnuDevice).deviceType
776 deviceID = onuInCache.(*OnuDevice).deviceID
777 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700778 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700779
780 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800781 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700782 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800783 deviceID, proxyDeviceID, ""); err != nil {
784 return NewErrCommunication("omci-request", log.Fields{
785 "source": dh.deviceType,
786 "destination": deviceType,
787 "onu-id": deviceID,
788 "proxy-device-id": proxyDeviceID}, err).Log()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700789 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800790 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530791}
792
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700793//ProcessInterAdapterMessage sends the proxied messages to the target device
794// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
795// is meant, and then send the unmarshalled omci message to this onu
796func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
797 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700798 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700799 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700800 fromTopic := msg.Header.FromTopic
801 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700802 toDeviceID := msg.Header.ToDeviceId
803 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700804
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700805 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700806
807 msgBody := msg.GetBody()
808
809 omciMsg := &ic.InterAdapterOmciMessage{}
810 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
811 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
812 return err
813 }
814
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700815 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700816 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
817 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800818 return NewErrNotFound("onu", log.Fields{
819 "device-id": dh.device.Id,
820 "onu-device-id": toDeviceID}, err).Log()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700821 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700822 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800823 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
824 return NewErrCommunication("send-failed", log.Fields{
825 "device-id": dh.device.Id,
826 "onu-device-id": toDeviceID}, err).Log()
827 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700828 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700829 log.Debugw("Proxy Address found in omci message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800830 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
831 return NewErrCommunication("send-failed", log.Fields{
832 "device-id": dh.device.Id,
833 "onu-device-id": toDeviceID}, err).Log()
834 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700835 }
836
837 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800838 return NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700839 }
840 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530841}
842
David K. Bainbridge794735f2020-02-11 21:01:37 -0800843func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700844 var intfID uint32
845 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000846 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700847 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700848 intfID = onuDevice.ProxyAddress.GetChannelId()
849 onuID = onuDevice.ProxyAddress.GetOnuId()
850 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700851 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700852 intfID = omciMsg.GetProxyAddress().GetChannelId()
853 onuID = omciMsg.GetProxyAddress().GetOnuId()
854 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700855 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700856 if connectStatus != voltha.ConnectStatus_REACHABLE {
857 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800858
859 return NewErrCommunication("unreachable", log.Fields{
860 "interface-id": intfID,
861 "onu-id": onuID}, nil).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -0700862 }
863
lcuie24ef182019-04-29 22:58:36 -0700864 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
865 isHexString := false
866 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
867 if decodeerr == nil {
868 isHexString = true
869 }
870
871 // TODO: OpenOLT Agent expects a hex string for OMCI packets rather than binary. Fix this in the agent and then we can pass binary Pkt: omciMsg.Message.
872 var omciMessage *oop.OmciMsg
873 if isHexString {
874 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
875 } else {
876 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
877 hex.Encode(hexPkt, omciMsg.Message)
878 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
879 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700880
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700881 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
882 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800883 return NewErrCommunication("omci-send-failed", log.Fields{
884 "interface-id": intfID,
885 "onu-id": onuID,
886 "message": omciMessage}, err).Log()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700887 }
lcuie24ef182019-04-29 22:58:36 -0700888 log.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800889 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700890}
891
David K. Bainbridge794735f2020-02-11 21:01:37 -0800892func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700893 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
npujarec5762e2020-01-01 14:08:48 +0530894 dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700895 // TODO: need resource manager
896 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700897 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +0530898 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400899 st, _ := status.FromError(err)
900 if st.Code() == codes.AlreadyExists {
901 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
902 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800903 return NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu}, err).Log()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400904 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700905 } else {
906 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
907 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800908 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700909}
910
David K. Bainbridge794735f2020-02-11 21:01:37 -0800911func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800912
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700913 channelID := onuDiscInd.GetIntfId()
914 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400915
Matteo Scandolo945e4012019-12-12 14:16:11 -0800916 log.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530917
cuilin20187b2a8c32019-03-26 19:52:28 -0700918 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400919 if sn != "" {
920 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400921 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800922 return NewErrInvalidValue(log.Fields{"serial-number": sn}, nil).Log()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400923 }
924
Amit Ghoshe5c6a852020-02-10 15:09:46 +0000925 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
926 log.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800927 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +0000928 }
929
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400930 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -0800931
932 // check the ONU is already know to the OLT
933 // NOTE the second time the ONU is discovered this should return a device
934 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
935
936 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800937 log.Warnw("core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -0800938 if e, ok := status.FromError(err); ok {
939 log.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
940 switch e.Code() {
941 case codes.Internal:
942 // this probably means NOT FOUND, so just create a new device
943 onuDevice = nil
944 case codes.DeadlineExceeded:
945 // if the call times out, cleanup and exit
946 dh.discOnus.Delete(sn)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800947 return NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err).Log()
Matteo Scandolo945e4012019-12-12 14:16:11 -0800948 }
949 }
950 }
951
952 if onuDevice == nil {
953 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
954 log.Infow("creating-new-onu", log.Fields{"sn": sn})
955 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -0400956 ponintfid := onuDiscInd.GetIntfId()
957 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +0530958 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -0400959 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400960
Matteo Scandolo945e4012019-12-12 14:16:11 -0800961 log.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
962
963 if err != nil {
964 // if we can't create an ID in resource manager,
965 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -0800966 dh.discOnus.Delete(sn)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800967 return NewErrAdapter("resource-manage-get-onu-id-failed", log.Fields{
968 "pon-interface-id": ponintfid,
969 "serial-number": sn}, err).Log()
Matteo Scandolo945e4012019-12-12 14:16:11 -0800970 }
971
972 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
973 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800974 dh.discOnus.Delete(sn)
975 dh.resourceMgr.FreeonuID(ctx, ponintfid, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
David K. Bainbridge794735f2020-02-11 21:01:37 -0800976 return NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
977 "pon-interface-id": ponintfid,
978 "serial-number": sn}, err).Log()
Matteo Scandolo945e4012019-12-12 14:16:11 -0800979 }
980
981 log.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400982 }
Matteo Scandolo945e4012019-12-12 14:16:11 -0800983
984 // we can now use the existing ONU Id
985 onuID = onuDevice.ProxyAddress.OnuId
986
Mahir Gunyele77977b2019-06-27 05:36:22 -0700987 //Insert the ONU into cache to use in OnuIndication.
988 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Matteo Scandolo945e4012019-12-12 14:16:11 -0800989 log.Debugw("onu-discovery-indication-key-create", log.Fields{"onuID": onuID,
990 "intfId": onuDiscInd.GetIntfId(), "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700991 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -0400992
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530993 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
994 dh.onus.Store(onuKey, onuDev)
Matteo Scandolo945e4012019-12-12 14:16:11 -0800995 log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400996
David K. Bainbridge794735f2020-02-11 21:01:37 -0800997 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
998 return NewErrAdapter("failed-to-update-device-state", log.Fields{
999 "device-id": onuDevice.Id,
1000 "serial-number": sn}, err).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -07001001 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001002 log.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001003 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
1004 return NewErrAdapter("onu-activation-failed", log.Fields{
1005 "device-id": onuDevice.Id,
1006 "serial-number": sn}, err).Log()
1007 }
1008 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001009}
1010
David K. Bainbridge794735f2020-02-11 21:01:37 -08001011func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001012 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1013
1014 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001015 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001016 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001017 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001018 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -07001019 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
1020 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001021 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301022
David K. Bainbridge794735f2020-02-11 21:01:37 -08001023 errFields := log.Fields{"device-id": dh.device.Id}
1024
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301025 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1026
Mahir Gunyele77977b2019-06-27 05:36:22 -07001027 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1028 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001029 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1030 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001031 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001032 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1033 if serialNumber != "" {
1034 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001035 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001036 } else {
1037 kwargs["onu_id"] = onuInd.OnuId
1038 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001039 errFields["onu-id"] = onuInd.OnuId
1040 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001041 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001042 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001043 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001044
David K. Bainbridge794735f2020-02-11 21:01:37 -08001045 if err != nil || onuDevice == nil {
1046 return NewErrNotFound("onu-device", errFields, err).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -07001047 }
1048
David K. Bainbridge794735f2020-02-11 21:01:37 -08001049 if onuDevice.ParentPortNo != ponPort {
1050 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
1051 "previousIntfId": onuDevice.ParentPortNo,
1052 "currentIntfId": ponPort})
1053 }
1054
1055 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
1056 log.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
1057 "expected_onu_id": onuDevice.ProxyAddress.OnuId,
1058 "received_onu_id": onuInd.OnuId})
1059 }
1060 if !foundInCache {
1061 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1062
1063 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId))
1064
1065 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001066 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001067 return NewErrCommunication("state-update-failed", errFields, err).Log()
1068 }
1069 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001070}
1071
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001072func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301073 ctx := context.TODO()
Matt Jeanneret53539512019-07-20 14:47:02 -04001074 log.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001075 if onuInd.AdminState == "down" {
1076 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1077 if onuInd.OperState != "down" {
1078 log.Warnw("ONU-admin-state-down", log.Fields{"operState": onuInd.OperState})
1079 onuInd.OperState = "down"
1080 }
1081 }
1082
David K. Bainbridge794735f2020-02-11 21:01:37 -08001083 switch onuInd.OperState {
1084 case "down":
Matt Jeanneret53539512019-07-20 14:47:02 -04001085 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001086 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301087 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001088 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1089 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001090 return NewErrCommunication("inter-adapter-send-failed", log.Fields{
1091 "onu-indicator": onuInd,
1092 "source": "openolt",
1093 "device-type": onuDevice.Type,
1094 "device-id": onuDevice.Id}, err).Log()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001095 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001096 case "up":
Matt Jeanneret53539512019-07-20 14:47:02 -04001097 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
1098 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301099 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001100 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1101 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001102 return NewErrCommunication("inter-adapter-send-failed", log.Fields{
1103 "onu-indicator": onuInd,
1104 "source": "openolt",
1105 "device-type": onuDevice.Type,
1106 "device-id": onuDevice.Id}, err).Log()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001107 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001108 default:
1109 return NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil).Log()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001110 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001111 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001112}
1113
cuilin20187b2a8c32019-03-26 19:52:28 -07001114func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1115 if serialNum != nil {
1116 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001117 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001118 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001119}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001120func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1121 decodedStr, err := hex.DecodeString(serialNum[4:])
1122 if err != nil {
1123 return nil, err
1124 }
1125 return &oop.SerialNumber{
1126 VendorId: []byte(serialNum[:4]),
1127 VendorSpecific: []byte(decodedStr),
1128 }, nil
1129}
cuilin20187b2a8c32019-03-26 19:52:28 -07001130
1131func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1132 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001133 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001134 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1135 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1136 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1137 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1138 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1139 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1140 return tmp
1141}
1142
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001143//UpdateFlowsBulk upates the bulk flow
1144func (dh *DeviceHandler) UpdateFlowsBulk() error {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001145 return ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001146}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001147
1148//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001149func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001150 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001151 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001152 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001153 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001154 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001155 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001156 return nil, NewErrNotFound("onu", log.Fields{
1157 "interface-id": parentPort,
1158 "onu-id": onuID}, err).Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -04001159 }
1160 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001161 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301162}
1163
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001164// SendPacketInToCore sends packet-in to core
1165// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1166// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001167func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001168 log.Debugw("send-packet-in-to-core", log.Fields{
1169 "port": logicalPort,
1170 "packet": hex.EncodeToString(packetPayload),
1171 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001172 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 return NewErrCommunication("packet-send-failed", log.Fields{
1174 "source": "adapter",
1175 "destination": "core",
1176 "device-id": dh.device.Id,
1177 "logical-port": logicalPort,
1178 "packet": hex.EncodeToString(packetPayload)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001179 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001180 log.Debugw("Sent packet-in to core successfully", log.Fields{
1181 "packet": hex.EncodeToString(packetPayload),
1182 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001183 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001184}
1185
A R Karthick1f85b802019-10-11 05:06:05 +00001186// AddUniPortToOnu adds the uni port to the onu device
1187func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1188 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301189
1190 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001191 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301192 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1193 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001194 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1195 }
1196 }
1197}
1198
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001199//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301200func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001201 log.Debugw("Received-incremental-flowupdate-in-device-handler", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001202 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001203 for _, flow := range flows.ToRemove.Items {
1204 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
npujarec5762e2020-01-01 14:08:48 +05301205 dh.flowMgr.RemoveFlow(ctx, flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001206 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301207
1208 for _, flow := range flows.ToAdd.Items {
1209 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
npujarec5762e2020-01-01 14:08:48 +05301210 dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301211 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001212 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001213 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001214 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001215 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001216 // dh.flowMgr.RemoveFlow(flow)
1217 }
1218 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001219
1220 if groups != nil {
1221 for _, group := range groups.ToAdd.Items {
npujarec5762e2020-01-01 14:08:48 +05301222 dh.flowMgr.AddGroup(ctx, group)
Esin Karamanccb714b2019-11-29 15:02:06 +00001223 }
1224 for _, group := range groups.ToUpdate.Items {
npujarec5762e2020-01-01 14:08:48 +05301225 dh.flowMgr.ModifyGroup(ctx, group)
Esin Karamanccb714b2019-11-29 15:02:06 +00001226 }
1227 if len(groups.ToRemove.Items) != 0 {
1228 log.Debug("Group delete operation is not supported for now")
1229 }
1230 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001231 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001232 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301233}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001234
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001235//DisableDevice disables the given device
1236//It marks the following for the given device:
1237//Device-Handler Admin-State : down
1238//Device Port-State: UNKNOWN
1239//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001240func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001241 /* On device disable ,admin state update has to be done prior sending request to agent since
1242 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001243 dh.lockDevice.Lock()
1244 dh.adminState = "down"
1245 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001246 if dh.Client != nil {
1247 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1248 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001249 dh.lockDevice.Lock()
1250 dh.adminState = "up"
1251 dh.lockDevice.Unlock()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001252 return NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err).Log()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001253 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001254 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001255 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001256 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001257 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001258 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301259
1260 dh.discOnus = sync.Map{}
1261 dh.onus = sync.Map{}
1262
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301263 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001264 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001265 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1266 for _, port := range cloned.Ports {
1267 if port.GetType() == voltha.Port_PON_OLT {
1268 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1269 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
1270 return err
1271 }
1272 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001273 }
1274
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001275 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001276 return nil
1277}
1278
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301279func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001280
1281 // Update onu state as unreachable in onu adapter
1282 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301283 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001284 //get the child device for the parent device
1285 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1286 if err != nil {
1287 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1288 }
1289 if onuDevices != nil {
1290 for _, onuDevice := range onuDevices.Items {
1291 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1292 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1293 if err != nil {
1294 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1295 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1296 }
1297
1298 }
1299 }
1300
1301}
1302
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001303//ReenableDevice re-enables the olt device after disable
1304//It marks the following for the given device:
1305//Device-Handler Admin-State : up
1306//Device Port-State: ACTIVE
1307//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001308func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001309 dh.lockDevice.Lock()
1310 dh.adminState = "up"
1311 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301312
1313 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1314 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301315 dh.lockDevice.Lock()
1316 dh.adminState = "down"
1317 dh.lockDevice.Unlock()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001318 return NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301319 }
1320 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001321 log.Debug("olt-reenabled")
1322
1323 cloned := proto.Clone(device).(*voltha.Device)
1324 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001325
kdarapu1afeceb2020-02-12 01:38:09 -05001326 if err := dh.disableAdminDownPorts(device); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001327 return NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err).Log()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001328 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001329 //Update the device oper status as ACTIVE
1330 cloned.OperStatus = voltha.OperStatus_ACTIVE
1331 dh.device = cloned
1332
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001333 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001334 return NewErrAdapter("state-update-failed", log.Fields{
1335 "device-id": device.Id,
1336 "connect-status": cloned.ConnectStatus,
1337 "oper-status": cloned.OperStatus}, err).Log()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001338 }
kesavand39e0aa32020-01-28 20:58:50 -05001339
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001340 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001341
1342 return nil
1343}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001344
npujarec5762e2020-01-01 14:08:48 +05301345func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001346 var uniID uint32
1347 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301348 for _, port := range onu.UniPorts {
1349 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001350 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1351 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301352 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301353 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001354 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301355 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301356 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001357 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301358 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001359 }
npujarec5762e2020-01-01 14:08:48 +05301360 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001361 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301362 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301363 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001364 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301365 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301366 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301367 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001368 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301369 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1370 }
npujarec5762e2020-01-01 14:08:48 +05301371 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1372 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301373 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1374 }
1375 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301376 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301377 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 +00001378 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001379 }
1380 return nil
1381}
1382
npujarec5762e2020-01-01 14:08:48 +05301383func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001384 nniUniID := -1
1385 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301386
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001387 if dh.resourceMgr == nil {
1388 return fmt.Errorf("no resource manager for deviceID %s", dh.deviceID)
1389 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001390 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301391 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301392 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001393 return NewErrPersistence("get", "nni", 0, nil, err).Log()
Devmalya Paul495b94a2019-08-27 19:42:00 -04001394 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301395 log.Debugw("NNI are ", log.Fields{"nni": nni})
1396 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301397 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301398 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1399 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301400 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301401 }
npujarec5762e2020-01-01 14:08:48 +05301402 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001403 }
npujarec5762e2020-01-01 14:08:48 +05301404 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001405 return NewErrPersistence("clear", "nni", 0, nil, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301406 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001407 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001408}
1409
1410// 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 +05301411func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001412 log.Debug("Function entry delete device")
1413 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001414 if dh.adminState == "deleted" {
1415 dh.lockDevice.Unlock()
1416 return nil
1417 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001418 dh.adminState = "deleted"
1419 dh.lockDevice.Unlock()
1420 /* Clear the KV store data associated with the all the UNI ports
1421 This clears up flow data and also resource map data for various
1422 other pon resources like alloc_id and gemport_id
1423 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001424 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301425 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1426 var ponPort uint32
1427 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1428 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301429 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301430 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001431 return NewErrNotFound("onu", log.Fields{
1432 "device-id": dh.device.Id,
1433 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301434 }
1435 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301436 onuID := make([]uint32, 1)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301437 log.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301438 if err = dh.clearUNIData(ctx, &onu); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301439 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1440 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301441 // Clear flowids for gem cache.
1442 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301443 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301444 }
1445 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301446 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301447 }
npujarec5762e2020-01-01 14:08:48 +05301448 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301449 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301450 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301451 if err != nil {
1452 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001453 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001454 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001455 /* Clear the flows from KV store associated with NNI port.
1456 There are mostly trap rules from NNI port (like LLDP)
1457 */
npujarec5762e2020-01-01 14:08:48 +05301458 if err := dh.clearNNIData(ctx); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301459 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001460 }
A R Karthick1f85b802019-10-11 05:06:05 +00001461
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001462 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301463 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001464 }
A R Karthick1f85b802019-10-11 05:06:05 +00001465
Devmalya Paul495b94a2019-08-27 19:42:00 -04001466 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301467 dh.onus.Range(func(key interface{}, value interface{}) bool {
1468 dh.onus.Delete(key)
1469 return true
1470 })
1471
Devmalya Paul495b94a2019-08-27 19:42:00 -04001472 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301473 // Stop the Stats collector
1474 dh.stopCollector <- true
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301475 // stop the heartbeat check routine
1476 dh.stopHeartbeatCheck <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001477 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001478 if dh.Client != nil {
npujarec5762e2020-01-01 14:08:48 +05301479 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001480 return NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001481 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001482 }
1483 cloned := proto.Clone(device).(*voltha.Device)
1484 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1485 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
npujarec5762e2020-01-01 14:08:48 +05301486 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001487 return NewErrAdapter("device-state-update-failed", log.Fields{
1488 "device-id": device.Id,
1489 "connect-status": cloned.ConnectStatus,
1490 "oper-status": cloned.OperStatus}, err).Log()
Devmalya Paul495b94a2019-08-27 19:42:00 -04001491 }
1492 return nil
1493}
1494
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001495//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001496func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1497 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001498 return NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001499 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001500 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001501 return nil
1502}
1503
David K. Bainbridge794735f2020-02-11 21:01:37 -08001504func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001505 log.Debugw("Received packet-in", log.Fields{
1506 "packet-indication": *packetIn,
1507 "packet": hex.EncodeToString(packetIn.Pkt),
1508 })
npujarec5762e2020-01-01 14:08:48 +05301509 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001510 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001511 return NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001512 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001513 log.Debugw("sending packet-in to core", log.Fields{
1514 "logicalPortNum": logicalPortNum,
1515 "packet": hex.EncodeToString(packetIn.Pkt),
1516 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001517 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001518 return NewErrCommunication("send-packet-in", log.Fields{
1519 "destination": "core",
1520 "source": dh.deviceType,
1521 "packet": hex.EncodeToString(packetIn.Pkt)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001522 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001523 log.Debugw("Success sending packet-in to core!", log.Fields{
1524 "packet": hex.EncodeToString(packetIn.Pkt),
1525 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001526 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001527}
1528
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001529// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301530func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001531 log.Debugw("incoming-packet-out", log.Fields{
1532 "deviceID": dh.deviceID,
1533 "egress_port_no": egressPortNo,
1534 "pkt-length": len(packet.Data),
1535 "packet": hex.EncodeToString(packet.Data),
1536 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001537
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001538 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001539 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001540 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1541 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301542 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1543 // Do not packet-out lldp packets on uni port.
1544 // ONOS has no clue about uni/nni ports, it just packets out on all
1545 // available ports on the Logical Switch. It should not be interested
1546 // in the UNI links.
1547 log.Debug("dropping-lldp-packet-out-on-uni")
1548 return nil
1549 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001550 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1551 if innerEthType == 0x8100 {
1552 // q-in-q 802.1ad or 802.1q double tagged packet.
1553 // slice out the outer tag.
1554 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1555 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001556 }
1557 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001558 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1559 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001560 uniID := UniIDFromPortNum(uint32(egressPortNo))
1561
npujarec5762e2020-01-01 14:08:48 +05301562 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001563 if err != nil {
1564 // In this case the openolt agent will receive the gemPortID as 0.
1565 // The agent tries to retrieve the gemPortID in this case.
1566 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001567 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1568 "packet": hex.EncodeToString(packet.Data),
1569 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001570 }
1571
1572 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001573
Matteo Scandolo6056e822019-11-13 14:05:29 -08001574 log.Debugw("sending-packet-to-onu", log.Fields{
1575 "egress_port_no": egressPortNo,
1576 "IntfId": intfID,
1577 "onuID": onuID,
1578 "uniID": uniID,
1579 "gemPortID": gemPortID,
1580 "packet": hex.EncodeToString(packet.Data),
1581 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001582
npujarec5762e2020-01-01 14:08:48 +05301583 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001584 return NewErrCommunication("packet-out-send", log.Fields{
1585 "source": "adapter",
1586 "destination": "onu",
1587 "egress-port-number": egressPortNo,
1588 "interface-id": intfID,
1589 "oni-id": onuID,
1590 "uni-id": uniID,
1591 "gem-port-id": gemPortID,
1592 "packet": hex.EncodeToString(packet.Data)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001593 }
1594 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001595 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1596 if err != nil {
1597 return NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err).Log()
1598 }
1599 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001600
Matteo Scandolo6056e822019-11-13 14:05:29 -08001601 log.Debugw("sending-packet-to-nni", log.Fields{
1602 "uplink_pkt": uplinkPkt,
1603 "packet": hex.EncodeToString(packet.Data),
1604 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001605
npujarec5762e2020-01-01 14:08:48 +05301606 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001607 return NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001608 }
1609 } else {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001610 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1611 "egress_port_no": egressPortNo,
1612 "egressPortType": egressPortType,
1613 "packet": hex.EncodeToString(packet.Data),
1614 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001615 }
1616 return nil
1617}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001618
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001619func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1620 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001621}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301622
1623func startHeartbeatCheck(dh *DeviceHandler) {
1624 // start the heartbeat check towards the OLT.
1625 var timerCheck *time.Timer
1626
1627 for {
1628 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1629 select {
1630 case <-heartbeatTimer.C:
1631 ctx, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1632 if heartBeat, err := dh.Client.HeartbeatCheck(ctx, new(oop.Empty)); err != nil {
1633 log.Error("Hearbeat failed")
1634 if timerCheck == nil {
1635 // start a after func, when expired will update the state to the core
1636 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, dh.updateStateUnreachable)
1637 }
1638 } else {
1639 if timerCheck != nil {
1640 if timerCheck.Stop() {
1641 log.Debug("We got hearbeat within the timeout")
1642 } else {
1643
1644 log.Debug("We got hearbeat after the timeout expired, changing the states")
1645 go dh.notifyChildDevices("up")
npujarec5762e2020-01-01 14:08:48 +05301646 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301647 voltha.OperStatus_ACTIVE); err != nil {
1648 log.Errorw("Failed to update device state", log.Fields{"deviceID": dh.device.Id, "error": err})
1649 }
1650 }
1651 timerCheck = nil
1652 }
1653 log.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
1654 }
1655 cancel()
1656 case <-dh.stopHeartbeatCheck:
1657 log.Debug("Stopping heart beat check")
1658 return
1659 }
1660 }
1661}
1662
1663func (dh *DeviceHandler) updateStateUnreachable() {
1664
1665 go dh.notifyChildDevices("unreachable")
1666 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001667 NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301668 }
1669}
kesavand39e0aa32020-01-28 20:58:50 -05001670
1671// EnablePort to enable Pon interface
1672func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
1673 log.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001674 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001675}
1676
1677// DisablePort to disable pon interface
1678func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
1679 log.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001680 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001681}
1682
kdarapu1afeceb2020-02-12 01:38:09 -05001683//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1684func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301685 ctx := context.Background()
kdarapu1afeceb2020-02-12 01:38:09 -05001686 log.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort})
kesavand39e0aa32020-01-28 20:58:50 -05001687 if port.GetType() == voltha.Port_ETHERNET_NNI {
1688 // Bug is opened for VOL-2505 to support NNI disable feature.
1689 log.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
1690 log.Fields{"Device": dh.device, "port": port})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001691 return NewErrAdapter("illegal-port-request", log.Fields{
1692 "port-type": port.GetType,
1693 "enable-state": enablePort}, nil).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001694 }
1695 // fetch interfaceid from PortNo
1696 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1697 ponIntf := &oop.Interface{IntfId: ponID}
1698 var operStatus voltha.OperStatus_Types
1699 if enablePort {
1700 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301701 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001702
1703 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001704 return NewErrAdapter("pon-port-enable-failed", log.Fields{
1705 "device-id": dh.device.Id,
1706 "port": port}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001707 }
1708 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001709 dh.activePorts.Store(ponID, true)
kesavand39e0aa32020-01-28 20:58:50 -05001710 log.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1711 } else {
1712 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301713 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001714 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001715 return NewErrAdapter("pon-port-disable-failed", log.Fields{
1716 "device-id": dh.device.Id,
1717 "port": port}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001718 }
1719 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001720 dh.activePorts.Store(ponID, false)
kesavand39e0aa32020-01-28 20:58:50 -05001721 log.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1722 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001723 if err := dh.coreProxy.PortStateUpdate(ctx, dh.deviceID, voltha.Port_PON_OLT, port.PortNo, operStatus); err != nil {
1724 return NewErrAdapter("port-state-update-failed", log.Fields{
1725 "device-id": dh.deviceID,
1726 "port": port.PortNo}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001727 }
1728 return nil
1729}
1730
kdarapu1afeceb2020-02-12 01:38:09 -05001731//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1732func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001733 cloned := proto.Clone(device).(*voltha.Device)
1734 // Disable the port and update the oper_port_status to core
1735 // if the Admin state of the port is disabled on reboot and re-enable device.
1736 for _, port := range cloned.Ports {
1737 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001738 if err := dh.DisablePort(port); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001739 return NewErrAdapter("port-disable-failed", log.Fields{
1740 "device-id": dh.deviceID,
1741 "port": port}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001742 }
1743 }
1744 }
1745 return nil
1746}
1747
1748//populateActivePorts to populate activePorts map
1749func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
1750 log.Info("populateActiveports", log.Fields{"Device": device})
1751 for _, port := range device.Ports {
1752 if port.Type == voltha.Port_ETHERNET_NNI {
1753 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001754 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001755 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001756 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001757 }
1758 }
1759 if port.Type == voltha.Port_PON_OLT {
1760 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001761 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001762 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001763 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001764 }
1765 }
1766 }
1767}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001768
1769// ChildDeviceLost deletes ONU and clears pon resources related to it.
1770func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
1771 log.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
1772 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1773 onuKey := dh.formOnuKey(IntfID, onuID)
1774 onuDevice, ok := dh.onus.Load(onuKey)
1775 if !ok {
1776 return NewErrAdapter("failed-to-load-onu-details",
1777 log.Fields{
1778 "device-id": dh.deviceID,
1779 "onu-id": onuID,
1780 "interface-id": IntfID}, nil).Log()
1781 }
1782 var sn *oop.SerialNumber
1783 var err error
1784 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
1785 return NewErrAdapter("failed-to-destringify-serial-number",
1786 log.Fields{
1787 "devicer-id": dh.deviceID,
1788 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
1789 }
1790 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
1791 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
1792 return NewErrAdapter("failed-to-delete-onu", log.Fields{
1793 "device-id": dh.deviceID,
1794 "onu-id": onuID}, err).Log()
1795 }
1796 //clear PON resources associated with ONU
1797 var onuGemData []rsrcMgr.OnuGemInfo
1798 if err := dh.resourceMgr.ResourceMgrs[IntfID].GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
1799 log.Errorw("Failed-to-get-onu-info-for-pon-port ", log.Fields{
1800 "device-id": dh.deviceID,
1801 "interface-id": IntfID,
1802 "error": err})
1803 }
1804
1805 for i, onu := range onuGemData {
1806 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
1807 log.Debugw("onu-data ", log.Fields{"onu": onu})
1808 if err := dh.clearUNIData(ctx, &onu); err != nil {
1809 log.Errorw("Failed-to-clear-uni-data-for-onu", log.Fields{
1810 "device-id": dh.deviceID,
1811 "onu-device": onu,
1812 "error": err})
1813 }
1814 // Clear flowids for gem cache.
1815 for _, gem := range onu.GemPorts {
1816 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
1817 }
1818 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
1819 dh.resourceMgr.UpdateOnuGemInfo(ctx, IntfID, onuGemData)
1820
1821 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
1822 break
1823 }
1824 }
1825 dh.onus.Delete(onuKey)
1826 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
1827 return nil
1828}