blob: 9683d31c4f2397af2a8bbc16111c77796581dc68 [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})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001003 //TODO: We put this sleep here to prevent the race between state update and onuIndication
1004 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
1005 //then the initialisation fails.
1006 time.Sleep(1 * time.Second)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001007 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
1008 return NewErrAdapter("onu-activation-failed", log.Fields{
1009 "device-id": onuDevice.Id,
1010 "serial-number": sn}, err).Log()
1011 }
1012 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001013}
1014
David K. Bainbridge794735f2020-02-11 21:01:37 -08001015func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001016 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1017
1018 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001019 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001020 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001021 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001022 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -07001023 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
1024 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001025 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301026
David K. Bainbridge794735f2020-02-11 21:01:37 -08001027 errFields := log.Fields{"device-id": dh.device.Id}
1028
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301029 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1030
Mahir Gunyele77977b2019-06-27 05:36:22 -07001031 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1032 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001033 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1034 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001035 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001036 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1037 if serialNumber != "" {
1038 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001039 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001040 } else {
1041 kwargs["onu_id"] = onuInd.OnuId
1042 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001043 errFields["onu-id"] = onuInd.OnuId
1044 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001045 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001046 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001047 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001048
David K. Bainbridge794735f2020-02-11 21:01:37 -08001049 if err != nil || onuDevice == nil {
1050 return NewErrNotFound("onu-device", errFields, err).Log()
cuilin20187b2a8c32019-03-26 19:52:28 -07001051 }
1052
David K. Bainbridge794735f2020-02-11 21:01:37 -08001053 if onuDevice.ParentPortNo != ponPort {
1054 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
1055 "previousIntfId": onuDevice.ParentPortNo,
1056 "currentIntfId": ponPort})
1057 }
1058
1059 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
1060 log.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
1061 "expected_onu_id": onuDevice.ProxyAddress.OnuId,
1062 "received_onu_id": onuInd.OnuId})
1063 }
1064 if !foundInCache {
1065 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1066
1067 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId))
1068
1069 }
1070 if err := dh.updateOnuStates(onuDevice, onuInd, foundInCache); err != nil {
1071 return NewErrCommunication("state-update-failed", errFields, err).Log()
1072 }
1073 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001074}
1075
David K. Bainbridge794735f2020-02-11 21:01:37 -08001076func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication, foundInCache bool) error {
npujarec5762e2020-01-01 14:08:48 +05301077 ctx := context.TODO()
Matt Jeanneret53539512019-07-20 14:47:02 -04001078 log.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001079 dh.updateOnuAdminState(onuInd)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001080 switch onuInd.OperState {
1081 case "down":
Matt Jeanneret53539512019-07-20 14:47:02 -04001082 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 -07001083 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301084 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001085 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1086 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001087 return NewErrCommunication("inter-adapter-send-failed", log.Fields{
1088 "onu-indicator": onuInd,
1089 "source": "openolt",
1090 "device-type": onuDevice.Type,
1091 "device-id": onuDevice.Id}, err).Log()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001092 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001093 case "up":
Scott Baker7eb0a932019-07-26 10:33:22 -07001094 // Ignore operstatus if device was found in cache
1095 if !foundInCache && onuDevice.OperStatus != common.OperStatus_DISCOVERED {
Matt Jeanneret53539512019-07-20 14:47:02 -04001096 log.Warnw("ignore-onu-indication", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId, "operStatus": onuDevice.OperStatus, "msgOperStatus": onuInd.OperState})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001097 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001098 }
Matt Jeanneret53539512019-07-20 14:47:02 -04001099 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
1100 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301101 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001102 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1103 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001104 return NewErrCommunication("inter-adapter-send-failed", log.Fields{
1105 "onu-indicator": onuInd,
1106 "source": "openolt",
1107 "device-type": onuDevice.Type,
1108 "device-id": onuDevice.Id}, err).Log()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001109 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001110 default:
1111 return NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil).Log()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001112 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001113 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001114}
1115
David K. Bainbridge794735f2020-02-11 21:01:37 -08001116func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) error {
1117 switch onuInd.AdminState {
1118 case "down":
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001119 if onuInd.OperState != "down" {
1120 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
1121 // Forcing the oper state change code to execute
1122 onuInd.OperState = "down"
1123 }
1124 // Port and logical port update is taken care of by oper state block
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125 case "up":
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001126 log.Debugln("received-onu-admin-state up")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001127 default:
1128 return NewErrInvalidValue(log.Fields{"admin-state": onuInd.AdminState}, nil).Log()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001129 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001130 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001131}
1132
cuilin20187b2a8c32019-03-26 19:52:28 -07001133func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1134 if serialNum != nil {
1135 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001136 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001137 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001138}
1139
1140func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1141 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001142 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001143 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1144 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1145 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1146 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1147 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1148 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1149 return tmp
1150}
1151
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001152//UpdateFlowsBulk upates the bulk flow
1153func (dh *DeviceHandler) UpdateFlowsBulk() error {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001154 return ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001155}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001156
1157//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001158func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001159 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001160 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001161 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001162 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001163 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001164 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001165 return nil, NewErrNotFound("onu", log.Fields{
1166 "interface-id": parentPort,
1167 "onu-id": onuID}, err).Log()
Girish Gowdru0c588b22019-04-23 23:24:56 -04001168 }
1169 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001170 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301171}
1172
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001173// SendPacketInToCore sends packet-in to core
1174// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1175// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001176func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001177 log.Debugw("send-packet-in-to-core", log.Fields{
1178 "port": logicalPort,
1179 "packet": hex.EncodeToString(packetPayload),
1180 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001181 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001182 return NewErrCommunication("packet-send-failed", log.Fields{
1183 "source": "adapter",
1184 "destination": "core",
1185 "device-id": dh.device.Id,
1186 "logical-port": logicalPort,
1187 "packet": hex.EncodeToString(packetPayload)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001188 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001189 log.Debugw("Sent packet-in to core successfully", log.Fields{
1190 "packet": hex.EncodeToString(packetPayload),
1191 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001192 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001193}
1194
A R Karthick1f85b802019-10-11 05:06:05 +00001195// AddUniPortToOnu adds the uni port to the onu device
1196func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1197 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301198
1199 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001200 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301201 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1202 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001203 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1204 }
1205 }
1206}
1207
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001208//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301209func (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 -04001210 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 -04001211 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001212 for _, flow := range flows.ToRemove.Items {
1213 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
npujarec5762e2020-01-01 14:08:48 +05301214 dh.flowMgr.RemoveFlow(ctx, flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001215 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301216
1217 for _, flow := range flows.ToAdd.Items {
1218 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
npujarec5762e2020-01-01 14:08:48 +05301219 dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301220 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001221 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001222 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001223 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001224 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001225 // dh.flowMgr.RemoveFlow(flow)
1226 }
1227 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001228
1229 if groups != nil {
1230 for _, group := range groups.ToAdd.Items {
npujarec5762e2020-01-01 14:08:48 +05301231 dh.flowMgr.AddGroup(ctx, group)
Esin Karamanccb714b2019-11-29 15:02:06 +00001232 }
1233 for _, group := range groups.ToUpdate.Items {
npujarec5762e2020-01-01 14:08:48 +05301234 dh.flowMgr.ModifyGroup(ctx, group)
Esin Karamanccb714b2019-11-29 15:02:06 +00001235 }
1236 if len(groups.ToRemove.Items) != 0 {
1237 log.Debug("Group delete operation is not supported for now")
1238 }
1239 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001240 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001241 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301242}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001243
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001244//DisableDevice disables the given device
1245//It marks the following for the given device:
1246//Device-Handler Admin-State : down
1247//Device Port-State: UNKNOWN
1248//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001249func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001250 /* On device disable ,admin state update has to be done prior sending request to agent since
1251 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001252 dh.lockDevice.Lock()
1253 dh.adminState = "down"
1254 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001255 if dh.Client != nil {
1256 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1257 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001258 dh.lockDevice.Lock()
1259 dh.adminState = "up"
1260 dh.lockDevice.Unlock()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001261 return NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err).Log()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001262 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001263 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001264 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001265 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001266 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001267 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301268
1269 dh.discOnus = sync.Map{}
1270 dh.onus = sync.Map{}
1271
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301272 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001273 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001274 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1275 for _, port := range cloned.Ports {
1276 if port.GetType() == voltha.Port_PON_OLT {
1277 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1278 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
1279 return err
1280 }
1281 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001282 }
1283
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001284 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001285 return nil
1286}
1287
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301288func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001289
1290 // Update onu state as unreachable in onu adapter
1291 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301292 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001293 //get the child device for the parent device
1294 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1295 if err != nil {
1296 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1297 }
1298 if onuDevices != nil {
1299 for _, onuDevice := range onuDevices.Items {
1300 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1301 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1302 if err != nil {
1303 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1304 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1305 }
1306
1307 }
1308 }
1309
1310}
1311
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001312//ReenableDevice re-enables the olt device after disable
1313//It marks the following for the given device:
1314//Device-Handler Admin-State : up
1315//Device Port-State: ACTIVE
1316//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001317func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001318 dh.lockDevice.Lock()
1319 dh.adminState = "up"
1320 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301321
1322 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1323 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301324 dh.lockDevice.Lock()
1325 dh.adminState = "down"
1326 dh.lockDevice.Unlock()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001327 return NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301328 }
1329 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001330 log.Debug("olt-reenabled")
1331
1332 cloned := proto.Clone(device).(*voltha.Device)
1333 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001334
kdarapu1afeceb2020-02-12 01:38:09 -05001335 if err := dh.disableAdminDownPorts(device); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001336 return NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err).Log()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001337 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001338 //Update the device oper status as ACTIVE
1339 cloned.OperStatus = voltha.OperStatus_ACTIVE
1340 dh.device = cloned
1341
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001342 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001343 return NewErrAdapter("state-update-failed", log.Fields{
1344 "device-id": device.Id,
1345 "connect-status": cloned.ConnectStatus,
1346 "oper-status": cloned.OperStatus}, err).Log()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001347 }
kesavand39e0aa32020-01-28 20:58:50 -05001348
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001349 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001350
1351 return nil
1352}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001353
npujarec5762e2020-01-01 14:08:48 +05301354func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001355 var uniID uint32
1356 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301357 for _, port := range onu.UniPorts {
1358 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001359 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1360 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301361 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301362 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001363 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301364 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301365 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001366 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301367 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001368 }
npujarec5762e2020-01-01 14:08:48 +05301369 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001370 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301371 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301372 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001373 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301374 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301375 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301376 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001377 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301378 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1379 }
npujarec5762e2020-01-01 14:08:48 +05301380 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1381 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301382 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1383 }
1384 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301385 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301386 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 +00001387 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001388 }
1389 return nil
1390}
1391
npujarec5762e2020-01-01 14:08:48 +05301392func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001393 nniUniID := -1
1394 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301395
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001396 if dh.resourceMgr == nil {
1397 return fmt.Errorf("no resource manager for deviceID %s", dh.deviceID)
1398 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001399 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301400 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301401 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001402 return NewErrPersistence("get", "nni", 0, nil, err).Log()
Devmalya Paul495b94a2019-08-27 19:42:00 -04001403 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301404 log.Debugw("NNI are ", log.Fields{"nni": nni})
1405 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301406 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301407 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1408 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301409 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301410 }
npujarec5762e2020-01-01 14:08:48 +05301411 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001412 }
npujarec5762e2020-01-01 14:08:48 +05301413 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001414 return NewErrPersistence("clear", "nni", 0, nil, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301415 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001416 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001417}
1418
1419// 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 +05301420func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001421 log.Debug("Function entry delete device")
1422 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001423 if dh.adminState == "deleted" {
1424 dh.lockDevice.Unlock()
1425 return nil
1426 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001427 dh.adminState = "deleted"
1428 dh.lockDevice.Unlock()
1429 /* Clear the KV store data associated with the all the UNI ports
1430 This clears up flow data and also resource map data for various
1431 other pon resources like alloc_id and gemport_id
1432 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001433 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301434 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1435 var ponPort uint32
1436 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1437 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301438 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301439 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001440 return NewErrNotFound("onu", log.Fields{
1441 "device-id": dh.device.Id,
1442 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301443 }
1444 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301445 onuID := make([]uint32, 1)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301446 log.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301447 if err = dh.clearUNIData(ctx, &onu); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301448 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1449 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301450 // Clear flowids for gem cache.
1451 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301452 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301453 }
1454 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301455 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301456 }
npujarec5762e2020-01-01 14:08:48 +05301457 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301458 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301459 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301460 if err != nil {
1461 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001462 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001463 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001464 /* Clear the flows from KV store associated with NNI port.
1465 There are mostly trap rules from NNI port (like LLDP)
1466 */
npujarec5762e2020-01-01 14:08:48 +05301467 if err := dh.clearNNIData(ctx); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301468 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001469 }
A R Karthick1f85b802019-10-11 05:06:05 +00001470
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001471 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301472 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001473 }
A R Karthick1f85b802019-10-11 05:06:05 +00001474
Devmalya Paul495b94a2019-08-27 19:42:00 -04001475 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301476 dh.onus.Range(func(key interface{}, value interface{}) bool {
1477 dh.onus.Delete(key)
1478 return true
1479 })
1480
Devmalya Paul495b94a2019-08-27 19:42:00 -04001481 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301482 // Stop the Stats collector
1483 dh.stopCollector <- true
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301484 // stop the heartbeat check routine
1485 dh.stopHeartbeatCheck <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001486 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001487 if dh.Client != nil {
npujarec5762e2020-01-01 14:08:48 +05301488 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001489 return NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001490 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001491 }
1492 cloned := proto.Clone(device).(*voltha.Device)
1493 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1494 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
npujarec5762e2020-01-01 14:08:48 +05301495 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001496 return NewErrAdapter("device-state-update-failed", log.Fields{
1497 "device-id": device.Id,
1498 "connect-status": cloned.ConnectStatus,
1499 "oper-status": cloned.OperStatus}, err).Log()
Devmalya Paul495b94a2019-08-27 19:42:00 -04001500 }
1501 return nil
1502}
1503
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001504//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001505func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1506 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001507 return NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001508 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001509 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001510 return nil
1511}
1512
David K. Bainbridge794735f2020-02-11 21:01:37 -08001513func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001514 log.Debugw("Received packet-in", log.Fields{
1515 "packet-indication": *packetIn,
1516 "packet": hex.EncodeToString(packetIn.Pkt),
1517 })
npujarec5762e2020-01-01 14:08:48 +05301518 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001519 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001520 return NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001521 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001522 log.Debugw("sending packet-in to core", log.Fields{
1523 "logicalPortNum": logicalPortNum,
1524 "packet": hex.EncodeToString(packetIn.Pkt),
1525 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001526 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001527 return NewErrCommunication("send-packet-in", log.Fields{
1528 "destination": "core",
1529 "source": dh.deviceType,
1530 "packet": hex.EncodeToString(packetIn.Pkt)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001531 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001532 log.Debugw("Success sending packet-in to core!", log.Fields{
1533 "packet": hex.EncodeToString(packetIn.Pkt),
1534 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001535 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001536}
1537
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001538// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301539func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001540 log.Debugw("incoming-packet-out", log.Fields{
1541 "deviceID": dh.deviceID,
1542 "egress_port_no": egressPortNo,
1543 "pkt-length": len(packet.Data),
1544 "packet": hex.EncodeToString(packet.Data),
1545 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001546
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001547 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001548 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001549 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1550 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301551 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1552 // Do not packet-out lldp packets on uni port.
1553 // ONOS has no clue about uni/nni ports, it just packets out on all
1554 // available ports on the Logical Switch. It should not be interested
1555 // in the UNI links.
1556 log.Debug("dropping-lldp-packet-out-on-uni")
1557 return nil
1558 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001559 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1560 if innerEthType == 0x8100 {
1561 // q-in-q 802.1ad or 802.1q double tagged packet.
1562 // slice out the outer tag.
1563 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1564 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001565 }
1566 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001567 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1568 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001569 uniID := UniIDFromPortNum(uint32(egressPortNo))
1570
npujarec5762e2020-01-01 14:08:48 +05301571 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001572 if err != nil {
1573 // In this case the openolt agent will receive the gemPortID as 0.
1574 // The agent tries to retrieve the gemPortID in this case.
1575 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001576 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1577 "packet": hex.EncodeToString(packet.Data),
1578 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001579 }
1580
1581 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001582
Matteo Scandolo6056e822019-11-13 14:05:29 -08001583 log.Debugw("sending-packet-to-onu", log.Fields{
1584 "egress_port_no": egressPortNo,
1585 "IntfId": intfID,
1586 "onuID": onuID,
1587 "uniID": uniID,
1588 "gemPortID": gemPortID,
1589 "packet": hex.EncodeToString(packet.Data),
1590 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001591
npujarec5762e2020-01-01 14:08:48 +05301592 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001593 return NewErrCommunication("packet-out-send", log.Fields{
1594 "source": "adapter",
1595 "destination": "onu",
1596 "egress-port-number": egressPortNo,
1597 "interface-id": intfID,
1598 "oni-id": onuID,
1599 "uni-id": uniID,
1600 "gem-port-id": gemPortID,
1601 "packet": hex.EncodeToString(packet.Data)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001602 }
1603 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001604 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1605 if err != nil {
1606 return NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err).Log()
1607 }
1608 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001609
Matteo Scandolo6056e822019-11-13 14:05:29 -08001610 log.Debugw("sending-packet-to-nni", log.Fields{
1611 "uplink_pkt": uplinkPkt,
1612 "packet": hex.EncodeToString(packet.Data),
1613 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001614
npujarec5762e2020-01-01 14:08:48 +05301615 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001616 return NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err).Log()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001617 }
1618 } else {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001619 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1620 "egress_port_no": egressPortNo,
1621 "egressPortType": egressPortType,
1622 "packet": hex.EncodeToString(packet.Data),
1623 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001624 }
1625 return nil
1626}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001627
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001628func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1629 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001630}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301631
1632func startHeartbeatCheck(dh *DeviceHandler) {
1633 // start the heartbeat check towards the OLT.
1634 var timerCheck *time.Timer
1635
1636 for {
1637 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1638 select {
1639 case <-heartbeatTimer.C:
1640 ctx, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1641 if heartBeat, err := dh.Client.HeartbeatCheck(ctx, new(oop.Empty)); err != nil {
1642 log.Error("Hearbeat failed")
1643 if timerCheck == nil {
1644 // start a after func, when expired will update the state to the core
1645 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, dh.updateStateUnreachable)
1646 }
1647 } else {
1648 if timerCheck != nil {
1649 if timerCheck.Stop() {
1650 log.Debug("We got hearbeat within the timeout")
1651 } else {
1652
1653 log.Debug("We got hearbeat after the timeout expired, changing the states")
1654 go dh.notifyChildDevices("up")
npujarec5762e2020-01-01 14:08:48 +05301655 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301656 voltha.OperStatus_ACTIVE); err != nil {
1657 log.Errorw("Failed to update device state", log.Fields{"deviceID": dh.device.Id, "error": err})
1658 }
1659 }
1660 timerCheck = nil
1661 }
1662 log.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
1663 }
1664 cancel()
1665 case <-dh.stopHeartbeatCheck:
1666 log.Debug("Stopping heart beat check")
1667 return
1668 }
1669 }
1670}
1671
1672func (dh *DeviceHandler) updateStateUnreachable() {
1673
1674 go dh.notifyChildDevices("unreachable")
1675 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 -08001676 NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301677 }
1678}
kesavand39e0aa32020-01-28 20:58:50 -05001679
1680// EnablePort to enable Pon interface
1681func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
1682 log.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001683 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001684}
1685
1686// DisablePort to disable pon interface
1687func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
1688 log.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001689 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001690}
1691
kdarapu1afeceb2020-02-12 01:38:09 -05001692//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1693func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301694 ctx := context.Background()
kdarapu1afeceb2020-02-12 01:38:09 -05001695 log.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort})
kesavand39e0aa32020-01-28 20:58:50 -05001696 if port.GetType() == voltha.Port_ETHERNET_NNI {
1697 // Bug is opened for VOL-2505 to support NNI disable feature.
1698 log.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
1699 log.Fields{"Device": dh.device, "port": port})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001700 return NewErrAdapter("illegal-port-request", log.Fields{
1701 "port-type": port.GetType,
1702 "enable-state": enablePort}, nil).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001703 }
1704 // fetch interfaceid from PortNo
1705 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1706 ponIntf := &oop.Interface{IntfId: ponID}
1707 var operStatus voltha.OperStatus_Types
1708 if enablePort {
1709 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301710 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001711
1712 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001713 return NewErrAdapter("pon-port-enable-failed", log.Fields{
1714 "device-id": dh.device.Id,
1715 "port": port}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001716 }
1717 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001718 dh.activePorts.Store(ponID, true)
kesavand39e0aa32020-01-28 20:58:50 -05001719 log.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1720 } else {
1721 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301722 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001723 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001724 return NewErrAdapter("pon-port-disable-failed", log.Fields{
1725 "device-id": dh.device.Id,
1726 "port": port}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001727 }
1728 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001729 dh.activePorts.Store(ponID, false)
kesavand39e0aa32020-01-28 20:58:50 -05001730 log.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1731 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001732 if err := dh.coreProxy.PortStateUpdate(ctx, dh.deviceID, voltha.Port_PON_OLT, port.PortNo, operStatus); err != nil {
1733 return NewErrAdapter("port-state-update-failed", log.Fields{
1734 "device-id": dh.deviceID,
1735 "port": port.PortNo}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001736 }
1737 return nil
1738}
1739
kdarapu1afeceb2020-02-12 01:38:09 -05001740//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1741func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001742 cloned := proto.Clone(device).(*voltha.Device)
1743 // Disable the port and update the oper_port_status to core
1744 // if the Admin state of the port is disabled on reboot and re-enable device.
1745 for _, port := range cloned.Ports {
1746 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001747 if err := dh.DisablePort(port); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001748 return NewErrAdapter("port-disable-failed", log.Fields{
1749 "device-id": dh.deviceID,
1750 "port": port}, err).Log()
kesavand39e0aa32020-01-28 20:58:50 -05001751 }
1752 }
1753 }
1754 return nil
1755}
1756
1757//populateActivePorts to populate activePorts map
1758func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
1759 log.Info("populateActiveports", log.Fields{"Device": device})
1760 for _, port := range device.Ports {
1761 if port.Type == voltha.Port_ETHERNET_NNI {
1762 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001763 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001764 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001765 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001766 }
1767 }
1768 if port.Type == voltha.Port_PON_OLT {
1769 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001770 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001771 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001772 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001773 }
1774 }
1775 }
1776}