blob: 60c128a7b15326c1bc216d5f04ea5d294535fd3c [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}
1120
1121func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1122 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001123 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001124 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1125 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1126 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1127 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1128 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1129 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1130 return tmp
1131}
1132
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001133//UpdateFlowsBulk upates the bulk flow
1134func (dh *DeviceHandler) UpdateFlowsBulk() error {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001135 return ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001136}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001137
1138//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001139func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001140 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001141 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001142 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001143 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001144 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001145 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001146 return nil, NewErrNotFound("onu", log.Fields{
1147 "interface-id": parentPort,
1148 "onu-id": onuID}, err).Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -04001149 }
1150 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001151 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301152}
1153
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001154// SendPacketInToCore sends packet-in to core
1155// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1156// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001157func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001158 log.Debugw("send-packet-in-to-core", log.Fields{
1159 "port": logicalPort,
1160 "packet": hex.EncodeToString(packetPayload),
1161 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001162 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 return NewErrCommunication("packet-send-failed", log.Fields{
1164 "source": "adapter",
1165 "destination": "core",
1166 "device-id": dh.device.Id,
1167 "logical-port": logicalPort,
1168 "packet": hex.EncodeToString(packetPayload)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001169 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001170 log.Debugw("Sent packet-in to core successfully", log.Fields{
1171 "packet": hex.EncodeToString(packetPayload),
1172 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001174}
1175
A R Karthick1f85b802019-10-11 05:06:05 +00001176// AddUniPortToOnu adds the uni port to the onu device
1177func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1178 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301179
1180 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001181 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301182 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1183 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001184 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1185 }
1186 }
1187}
1188
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001189//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301190func (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 -04001191 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 -04001192 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001193 for _, flow := range flows.ToRemove.Items {
1194 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
npujarec5762e2020-01-01 14:08:48 +05301195 dh.flowMgr.RemoveFlow(ctx, flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001196 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301197
1198 for _, flow := range flows.ToAdd.Items {
1199 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
npujarec5762e2020-01-01 14:08:48 +05301200 dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301201 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001202 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001203 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001204 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001205 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001206 // dh.flowMgr.RemoveFlow(flow)
1207 }
1208 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001209
1210 if groups != nil {
1211 for _, group := range groups.ToAdd.Items {
npujarec5762e2020-01-01 14:08:48 +05301212 dh.flowMgr.AddGroup(ctx, group)
Esin Karamanccb714b2019-11-29 15:02:06 +00001213 }
1214 for _, group := range groups.ToUpdate.Items {
npujarec5762e2020-01-01 14:08:48 +05301215 dh.flowMgr.ModifyGroup(ctx, group)
Esin Karamanccb714b2019-11-29 15:02:06 +00001216 }
1217 if len(groups.ToRemove.Items) != 0 {
1218 log.Debug("Group delete operation is not supported for now")
1219 }
1220 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001221 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001222 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301223}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001224
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001225//DisableDevice disables the given device
1226//It marks the following for the given device:
1227//Device-Handler Admin-State : down
1228//Device Port-State: UNKNOWN
1229//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001230func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001231 /* On device disable ,admin state update has to be done prior sending request to agent since
1232 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001233 dh.lockDevice.Lock()
1234 dh.adminState = "down"
1235 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001236 if dh.Client != nil {
1237 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1238 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001239 dh.lockDevice.Lock()
1240 dh.adminState = "up"
1241 dh.lockDevice.Unlock()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001242 return NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err).Log()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001243 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001244 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001245 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001246 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001247 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001248 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301249
1250 dh.discOnus = sync.Map{}
1251 dh.onus = sync.Map{}
1252
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301253 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001254 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001255 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1256 for _, port := range cloned.Ports {
1257 if port.GetType() == voltha.Port_PON_OLT {
1258 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1259 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
1260 return err
1261 }
1262 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001263 }
1264
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001265 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001266 return nil
1267}
1268
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301269func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001270
1271 // Update onu state as unreachable in onu adapter
1272 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301273 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001274 //get the child device for the parent device
1275 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1276 if err != nil {
1277 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1278 }
1279 if onuDevices != nil {
1280 for _, onuDevice := range onuDevices.Items {
1281 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1282 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1283 if err != nil {
1284 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1285 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1286 }
1287
1288 }
1289 }
1290
1291}
1292
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001293//ReenableDevice re-enables the olt device after disable
1294//It marks the following for the given device:
1295//Device-Handler Admin-State : up
1296//Device Port-State: ACTIVE
1297//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001298func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001299 dh.lockDevice.Lock()
1300 dh.adminState = "up"
1301 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301302
1303 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1304 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301305 dh.lockDevice.Lock()
1306 dh.adminState = "down"
1307 dh.lockDevice.Unlock()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001308 return NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301309 }
1310 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001311 log.Debug("olt-reenabled")
1312
1313 cloned := proto.Clone(device).(*voltha.Device)
1314 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001315
kdarapu1afeceb2020-02-12 01:38:09 -05001316 if err := dh.disableAdminDownPorts(device); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001317 return NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err).Log()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001318 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001319 //Update the device oper status as ACTIVE
1320 cloned.OperStatus = voltha.OperStatus_ACTIVE
1321 dh.device = cloned
1322
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001323 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001324 return NewErrAdapter("state-update-failed", log.Fields{
1325 "device-id": device.Id,
1326 "connect-status": cloned.ConnectStatus,
1327 "oper-status": cloned.OperStatus}, err).Log()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001328 }
kesavand39e0aa32020-01-28 20:58:50 -05001329
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001330 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001331
1332 return nil
1333}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001334
npujarec5762e2020-01-01 14:08:48 +05301335func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001336 var uniID uint32
1337 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301338 for _, port := range onu.UniPorts {
1339 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001340 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1341 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301342 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301343 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001344 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301345 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301346 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001347 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301348 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001349 }
npujarec5762e2020-01-01 14:08:48 +05301350 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001351 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301352 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301353 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001354 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301355 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301356 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301357 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001358 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301359 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1360 }
npujarec5762e2020-01-01 14:08:48 +05301361 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1362 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301363 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1364 }
1365 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301366 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301367 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 +00001368 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001369 }
1370 return nil
1371}
1372
npujarec5762e2020-01-01 14:08:48 +05301373func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001374 nniUniID := -1
1375 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301376
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001377 if dh.resourceMgr == nil {
1378 return fmt.Errorf("no resource manager for deviceID %s", dh.deviceID)
1379 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001380 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301381 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301382 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 return NewErrPersistence("get", "nni", 0, nil, err).Log()
Devmalya Paul495b94a2019-08-27 19:42:00 -04001384 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301385 log.Debugw("NNI are ", log.Fields{"nni": nni})
1386 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301387 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301388 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1389 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301390 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301391 }
npujarec5762e2020-01-01 14:08:48 +05301392 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001393 }
npujarec5762e2020-01-01 14:08:48 +05301394 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001395 return NewErrPersistence("clear", "nni", 0, nil, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301396 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001397 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001398}
1399
1400// 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 +05301401func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001402 log.Debug("Function entry delete device")
1403 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001404 if dh.adminState == "deleted" {
1405 dh.lockDevice.Unlock()
1406 return nil
1407 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001408 dh.adminState = "deleted"
1409 dh.lockDevice.Unlock()
1410 /* Clear the KV store data associated with the all the UNI ports
1411 This clears up flow data and also resource map data for various
1412 other pon resources like alloc_id and gemport_id
1413 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001414 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301415 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1416 var ponPort uint32
1417 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1418 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301419 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301420 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001421 return NewErrNotFound("onu", log.Fields{
1422 "device-id": dh.device.Id,
1423 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301424 }
1425 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301426 onuID := make([]uint32, 1)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301427 log.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301428 if err = dh.clearUNIData(ctx, &onu); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301429 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1430 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301431 // Clear flowids for gem cache.
1432 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301433 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301434 }
1435 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301436 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301437 }
npujarec5762e2020-01-01 14:08:48 +05301438 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301439 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301440 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301441 if err != nil {
1442 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001443 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001444 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001445 /* Clear the flows from KV store associated with NNI port.
1446 There are mostly trap rules from NNI port (like LLDP)
1447 */
npujarec5762e2020-01-01 14:08:48 +05301448 if err := dh.clearNNIData(ctx); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301449 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001450 }
A R Karthick1f85b802019-10-11 05:06:05 +00001451
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001452 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301453 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001454 }
A R Karthick1f85b802019-10-11 05:06:05 +00001455
Devmalya Paul495b94a2019-08-27 19:42:00 -04001456 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301457 dh.onus.Range(func(key interface{}, value interface{}) bool {
1458 dh.onus.Delete(key)
1459 return true
1460 })
1461
Devmalya Paul495b94a2019-08-27 19:42:00 -04001462 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301463 // Stop the Stats collector
1464 dh.stopCollector <- true
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301465 // stop the heartbeat check routine
1466 dh.stopHeartbeatCheck <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001467 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001468 if dh.Client != nil {
npujarec5762e2020-01-01 14:08:48 +05301469 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001470 return NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001471 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001472 }
1473 cloned := proto.Clone(device).(*voltha.Device)
1474 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1475 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
npujarec5762e2020-01-01 14:08:48 +05301476 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001477 return NewErrAdapter("device-state-update-failed", log.Fields{
1478 "device-id": device.Id,
1479 "connect-status": cloned.ConnectStatus,
1480 "oper-status": cloned.OperStatus}, err).Log()
Devmalya Paul495b94a2019-08-27 19:42:00 -04001481 }
1482 return nil
1483}
1484
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001485//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001486func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1487 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001488 return NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001489 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001490 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001491 return nil
1492}
1493
David K. Bainbridge794735f2020-02-11 21:01:37 -08001494func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001495 log.Debugw("Received packet-in", log.Fields{
1496 "packet-indication": *packetIn,
1497 "packet": hex.EncodeToString(packetIn.Pkt),
1498 })
npujarec5762e2020-01-01 14:08:48 +05301499 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001500 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001501 return NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001502 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001503 log.Debugw("sending packet-in to core", log.Fields{
1504 "logicalPortNum": logicalPortNum,
1505 "packet": hex.EncodeToString(packetIn.Pkt),
1506 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001507 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001508 return NewErrCommunication("send-packet-in", log.Fields{
1509 "destination": "core",
1510 "source": dh.deviceType,
1511 "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("Success sending packet-in to core!", log.Fields{
1514 "packet": hex.EncodeToString(packetIn.Pkt),
1515 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001516 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001517}
1518
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001519// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301520func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001521 log.Debugw("incoming-packet-out", log.Fields{
1522 "deviceID": dh.deviceID,
1523 "egress_port_no": egressPortNo,
1524 "pkt-length": len(packet.Data),
1525 "packet": hex.EncodeToString(packet.Data),
1526 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001527
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001528 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001529 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001530 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1531 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301532 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1533 // Do not packet-out lldp packets on uni port.
1534 // ONOS has no clue about uni/nni ports, it just packets out on all
1535 // available ports on the Logical Switch. It should not be interested
1536 // in the UNI links.
1537 log.Debug("dropping-lldp-packet-out-on-uni")
1538 return nil
1539 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001540 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1541 if innerEthType == 0x8100 {
1542 // q-in-q 802.1ad or 802.1q double tagged packet.
1543 // slice out the outer tag.
1544 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1545 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001546 }
1547 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001548 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1549 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001550 uniID := UniIDFromPortNum(uint32(egressPortNo))
1551
npujarec5762e2020-01-01 14:08:48 +05301552 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001553 if err != nil {
1554 // In this case the openolt agent will receive the gemPortID as 0.
1555 // The agent tries to retrieve the gemPortID in this case.
1556 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001557 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1558 "packet": hex.EncodeToString(packet.Data),
1559 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001560 }
1561
1562 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001563
Matteo Scandolo6056e822019-11-13 14:05:29 -08001564 log.Debugw("sending-packet-to-onu", log.Fields{
1565 "egress_port_no": egressPortNo,
1566 "IntfId": intfID,
1567 "onuID": onuID,
1568 "uniID": uniID,
1569 "gemPortID": gemPortID,
1570 "packet": hex.EncodeToString(packet.Data),
1571 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001572
npujarec5762e2020-01-01 14:08:48 +05301573 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001574 return NewErrCommunication("packet-out-send", log.Fields{
1575 "source": "adapter",
1576 "destination": "onu",
1577 "egress-port-number": egressPortNo,
1578 "interface-id": intfID,
1579 "oni-id": onuID,
1580 "uni-id": uniID,
1581 "gem-port-id": gemPortID,
1582 "packet": hex.EncodeToString(packet.Data)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001583 }
1584 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001585 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1586 if err != nil {
1587 return NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err).Log()
1588 }
1589 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001590
Matteo Scandolo6056e822019-11-13 14:05:29 -08001591 log.Debugw("sending-packet-to-nni", log.Fields{
1592 "uplink_pkt": uplinkPkt,
1593 "packet": hex.EncodeToString(packet.Data),
1594 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001595
npujarec5762e2020-01-01 14:08:48 +05301596 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001597 return NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001598 }
1599 } else {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001600 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1601 "egress_port_no": egressPortNo,
1602 "egressPortType": egressPortType,
1603 "packet": hex.EncodeToString(packet.Data),
1604 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001605 }
1606 return nil
1607}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001608
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001609func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1610 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001611}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301612
1613func startHeartbeatCheck(dh *DeviceHandler) {
1614 // start the heartbeat check towards the OLT.
1615 var timerCheck *time.Timer
1616
1617 for {
1618 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1619 select {
1620 case <-heartbeatTimer.C:
1621 ctx, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1622 if heartBeat, err := dh.Client.HeartbeatCheck(ctx, new(oop.Empty)); err != nil {
1623 log.Error("Hearbeat failed")
1624 if timerCheck == nil {
1625 // start a after func, when expired will update the state to the core
1626 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, dh.updateStateUnreachable)
1627 }
1628 } else {
1629 if timerCheck != nil {
1630 if timerCheck.Stop() {
1631 log.Debug("We got hearbeat within the timeout")
1632 } else {
1633
1634 log.Debug("We got hearbeat after the timeout expired, changing the states")
1635 go dh.notifyChildDevices("up")
npujarec5762e2020-01-01 14:08:48 +05301636 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301637 voltha.OperStatus_ACTIVE); err != nil {
1638 log.Errorw("Failed to update device state", log.Fields{"deviceID": dh.device.Id, "error": err})
1639 }
1640 }
1641 timerCheck = nil
1642 }
1643 log.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
1644 }
1645 cancel()
1646 case <-dh.stopHeartbeatCheck:
1647 log.Debug("Stopping heart beat check")
1648 return
1649 }
1650 }
1651}
1652
1653func (dh *DeviceHandler) updateStateUnreachable() {
1654
1655 go dh.notifyChildDevices("unreachable")
1656 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 -08001657 NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301658 }
1659}
kesavand39e0aa32020-01-28 20:58:50 -05001660
1661// EnablePort to enable Pon interface
1662func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
1663 log.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001664 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001665}
1666
1667// DisablePort to disable pon interface
1668func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
1669 log.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001670 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001671}
1672
kdarapu1afeceb2020-02-12 01:38:09 -05001673//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1674func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301675 ctx := context.Background()
kdarapu1afeceb2020-02-12 01:38:09 -05001676 log.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort})
kesavand39e0aa32020-01-28 20:58:50 -05001677 if port.GetType() == voltha.Port_ETHERNET_NNI {
1678 // Bug is opened for VOL-2505 to support NNI disable feature.
1679 log.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
1680 log.Fields{"Device": dh.device, "port": port})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001681 return NewErrAdapter("illegal-port-request", log.Fields{
1682 "port-type": port.GetType,
1683 "enable-state": enablePort}, nil).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001684 }
1685 // fetch interfaceid from PortNo
1686 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1687 ponIntf := &oop.Interface{IntfId: ponID}
1688 var operStatus voltha.OperStatus_Types
1689 if enablePort {
1690 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301691 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001692
1693 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001694 return NewErrAdapter("pon-port-enable-failed", log.Fields{
1695 "device-id": dh.device.Id,
1696 "port": port}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001697 }
1698 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001699 dh.activePorts.Store(ponID, true)
kesavand39e0aa32020-01-28 20:58:50 -05001700 log.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1701 } else {
1702 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301703 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001704 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001705 return NewErrAdapter("pon-port-disable-failed", log.Fields{
1706 "device-id": dh.device.Id,
1707 "port": port}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001708 }
1709 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001710 dh.activePorts.Store(ponID, false)
kesavand39e0aa32020-01-28 20:58:50 -05001711 log.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1712 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001713 if err := dh.coreProxy.PortStateUpdate(ctx, dh.deviceID, voltha.Port_PON_OLT, port.PortNo, operStatus); err != nil {
1714 return NewErrAdapter("port-state-update-failed", log.Fields{
1715 "device-id": dh.deviceID,
1716 "port": port.PortNo}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001717 }
1718 return nil
1719}
1720
kdarapu1afeceb2020-02-12 01:38:09 -05001721//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1722func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001723 cloned := proto.Clone(device).(*voltha.Device)
1724 // Disable the port and update the oper_port_status to core
1725 // if the Admin state of the port is disabled on reboot and re-enable device.
1726 for _, port := range cloned.Ports {
1727 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001728 if err := dh.DisablePort(port); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001729 return NewErrAdapter("port-disable-failed", log.Fields{
1730 "device-id": dh.deviceID,
1731 "port": port}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001732 }
1733 }
1734 }
1735 return nil
1736}
1737
1738//populateActivePorts to populate activePorts map
1739func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
1740 log.Info("populateActiveports", log.Fields{"Device": device})
1741 for _, port := range device.Ports {
1742 if port.Type == voltha.Port_ETHERNET_NNI {
1743 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001744 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001745 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001746 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001747 }
1748 }
1749 if port.Type == voltha.Port_PON_OLT {
1750 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001751 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001752 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001753 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001754 }
1755 }
1756 }
1757}