blob: 111a87c5b90861003ca84fc1443f6f24311b701e [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneret1359c732019-08-01 21:40:02 -040022 "encoding/hex"
cuilin20187b2a8c32019-03-26 19:52:28 -070023 "fmt"
Girish Gowdracefae192020-03-19 18:14:10 -070024 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
cuilin20187b2a8c32019-03-26 19:52:28 -070025 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040026 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070027 "strconv"
28 "strings"
29 "sync"
30 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053031
Chaitrashree G Sb2b62dd2019-07-24 21:47:04 -040032 "google.golang.org/grpc/codes"
33
Matteo Scandolo945e4012019-12-12 14:16:11 -080034 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070035 "github.com/gogo/protobuf/proto"
36 "github.com/golang/protobuf/ptypes"
Esin Karamanccb714b2019-11-29 15:02:06 +000037 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
38 "github.com/opencord/voltha-lib-go/v3/pkg/log"
39 "github.com/opencord/voltha-lib-go/v3/pkg/pmmetrics"
Thomas Lee S94109f12020-03-03 16:39:29 +053040 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080041 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000042 "github.com/opencord/voltha-protos/v3/go/common"
43 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
44 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
45 oop "github.com/opencord/voltha-protos/v3/go/openolt"
46 "github.com/opencord/voltha-protos/v3/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070047 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040048 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053049)
50
salmansiddiqui7ac62132019-08-22 03:58:50 +000051// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040052const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000053 MaxRetry = 10
54 MaxTimeOutInMs = 500
Girish Gowdracefae192020-03-19 18:14:10 -070055 InvalidPort = 0xffffffff
Manikkaraj kb1d51442019-07-23 10:41:02 -040056)
57
Girish Gowdracefae192020-03-19 18:14:10 -070058// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
59type pendingFlowRemoveDataKey struct {
60 intfID uint32
61 onuID uint32
62 uniID uint32
63}
64
65// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
66// This holds the number of pending flow removes and also a signal channel to
67// to indicate the receiver when all flow removes are handled
68type pendingFlowRemoveData struct {
69 pendingFlowRemoveCount uint32
70 allFlowsRemoved chan struct{}
71}
72
Phaneendra Manda4c62c802019-03-06 21:37:49 +053073//DeviceHandler will interact with the OLT device.
74type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070075 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070076 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040077 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070078 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053079 coreProxy adapterif.CoreProxy
80 AdapterProxy adapterif.AdapterProxy
81 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070082 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070083 exitChannel chan int
84 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053085 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070086 transitionMap *TransitionMap
87 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053088 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040089 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053090 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053091
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +053092 discOnus sync.Map
93 onus sync.Map
94 portStats *OpenOltStatisticsMgr
95 metrics *pmmetrics.PmMetrics
96 stopCollector chan bool
97 stopHeartbeatCheck chan bool
Chaitrashree G Sef088112020-02-03 21:39:27 -050098 activePorts sync.Map
Chaitrashree G Sa4649252020-03-11 21:24:11 -040099 stopIndications chan bool
Girish Gowdracefae192020-03-19 18:14:10 -0700100
101 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
102 // subscriber basis for the number of pending flow removes. This data is used
103 // to process all the flow removes for a subscriber before handling flow adds.
104 // Interleaving flow delete and flow add processing has known to cause PON resource
105 // management contentions on a per subscriber bases, so we need ensure ordering.
106 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700107}
108
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700109//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700110type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700112 deviceType string
113 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 onuID uint32
115 intfID uint32
116 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +0000117 uniPorts map[uint32]struct{}
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530118 losRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700119}
120
Naga Manjunath7615e552019-10-11 22:35:47 +0530121var pmNames = []string{
122 "rx_bytes",
123 "rx_packets",
124 "rx_mcast_packets",
125 "rx_bcast_packets",
126 "tx_bytes",
127 "tx_packets",
128 "tx_mcast_packets",
129 "tx_bcast_packets",
130}
131
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700132//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530133func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700134 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700135 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700136 device.deviceType = deviceTp
137 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700138 device.onuID = onuID
139 device.intfID = intfID
140 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000141 device.uniPorts = make(map[uint32]struct{})
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530142 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700143 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530144}
145
146//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530147func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700148 var dh DeviceHandler
149 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400150 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400151 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700152 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700153 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700154 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400155 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700156 dh.device = cloned
157 dh.openOLT = adapter
158 dh.exitChannel = make(chan int, 1)
159 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530160 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530161 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530162 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 -0500163 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400164 dh.stopIndications = make(chan bool, 1)
Girish Gowdracefae192020-03-19 18:14:10 -0700165 dh.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
166
cuilin20187b2a8c32019-03-26 19:52:28 -0700167 //TODO initialize the support classes.
168 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530169}
170
171// start save the device to the data model
172func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700173 dh.lockDevice.Lock()
174 defer dh.lockDevice.Unlock()
175 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
176 // Add the initial device to the local model
177 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530178}
179
180// stop stops the device dh. Not much to do for now
181func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700182 dh.lockDevice.Lock()
183 defer dh.lockDevice.Unlock()
184 log.Debug("stopping-device-agent")
185 dh.exitChannel <- 1
186 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530187}
188
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400189func macifyIP(ip net.IP) string {
190 if len(ip) > 0 {
191 oct1 := strconv.FormatInt(int64(ip[12]), 16)
192 oct2 := strconv.FormatInt(int64(ip[13]), 16)
193 oct3 := strconv.FormatInt(int64(ip[14]), 16)
194 oct4 := strconv.FormatInt(int64(ip[15]), 16)
195 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
196 }
197 return ""
198}
199
200func generateMacFromHost(host string) (string, error) {
201 var genmac string
202 var addr net.IP
203 var ips []string
204 var err error
205
206 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
207
208 if addr = net.ParseIP(host); addr == nil {
209 log.Debugw("looking-up-hostname", log.Fields{"host": host})
210
211 if ips, err = net.LookupHost(host); err == nil {
212 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
213 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000214 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400215 }
216 genmac = macifyIP(addr)
217 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
218 return genmac, nil
219 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000220 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400221 }
222
223 genmac = macifyIP(addr)
224 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
225 return genmac, nil
226}
227
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530228func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700229 slist := strings.Split(mac, ":")
230 result := make([]uint32, len(slist))
231 var err error
232 var tmp int64
233 for index, val := range slist {
234 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
235 return []uint32{1, 2, 3, 4, 5, 6}
236 }
237 result[index] = uint32(tmp)
238 }
239 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530240}
241
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700242//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 -0800243func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530244
David K. Bainbridge794735f2020-02-11 21:01:37 -0800245 switch portType {
246 case voltha.Port_ETHERNET_NNI:
247 return fmt.Sprintf("nni-%d", portNum), nil
248 case voltha.Port_PON_OLT:
249 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700250 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800251
Girish Kumarf26e4882020-03-05 06:49:10 +0000252 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530253}
254
David K. Bainbridge794735f2020-02-11 21:01:37 -0800255func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000256 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700257 if state == "up" {
258 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500259 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500260 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700261 } else {
262 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500263 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700264 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700265 portNum := IntfIDToPortNo(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800266 label, err := GetportLabel(portNum, portType)
267 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000268 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400269 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500270
271 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
272 if err != nil || device == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000273 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500274 }
275 if device.Ports != nil {
276 for _, dPort := range device.Ports {
277 if dPort.Type == portType && dPort.PortNo == portNum {
278 log.Debug("port-already-exists-updating-oper-status-of-port")
279 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530280 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800281 "device-id": dh.device.Id,
282 "port-type": portType,
283 "port-number": portNum,
Girish Kumarf26e4882020-03-05 06:49:10 +0000284 "oper-status": operStatus}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800285
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500286 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800287 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500288 }
289 }
290 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400291 // Now create Port
292 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700293 PortNo: portNum,
294 Label: label,
295 Type: portType,
296 OperStatus: operStatus,
297 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500298 log.Debugw("Sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700299 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700300 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000301 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800302 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000303 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400304 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800305 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530306}
307
308// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800309func (dh *DeviceHandler) readIndications(ctx context.Context) error {
310 defer log.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530311 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700312 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000313 return olterrors.NewErrCommunication("fail-to-read-indications", log.Fields{"device-id": dh.device.Id}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700314 }
315 if indications == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000316 return olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700317 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400318 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530319 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400320 if err != nil || device == nil {
321 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000322 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400323 }
324 // When the device is in DISABLED and Adapter container restarts, we need to
325 // rebuild the locally maintained admin state.
326 if device.AdminState == voltha.AdminState_DISABLED {
327 dh.lockDevice.Lock()
328 dh.adminState = "down"
329 dh.lockDevice.Unlock()
330 }
331
David Bainbridgef5879ca2019-12-13 21:17:54 +0000332 // Create an exponential backoff around re-enabling indications. The
333 // maximum elapsed time for the back off is set to 0 so that we will
334 // continue to retry. The max interval defaults to 1m, but is set
335 // here for code clarity
336 indicationBackoff := backoff.NewExponentialBackOff()
337 indicationBackoff.MaxElapsedTime = 0
338 indicationBackoff.MaxInterval = 1 * time.Minute
cuilin20187b2a8c32019-03-26 19:52:28 -0700339 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400340 select {
341 case <-dh.stopIndications:
342 log.Debugw("Stopping-collecting-indications-for-OLT", log.Fields{"deviceID:": dh.deviceID})
343 break
344 default:
345 indication, err := indications.Recv()
346 if err == io.EOF {
347 log.Infow("EOF for indications", log.Fields{"err": err})
348 // Use an exponential back off to prevent getting into a tight loop
349 duration := indicationBackoff.NextBackOff()
350 if duration == backoff.Stop {
351 // If we reach a maximum then warn and reset the backoff
352 // timer and keep attempting.
353 log.Warnw("Maximum indication backoff reached, resetting backoff timer",
354 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
355 indicationBackoff.Reset()
356 }
357 time.Sleep(indicationBackoff.NextBackOff())
358 indications, err = dh.Client.EnableIndication(ctx, new(oop.Empty))
359 if err != nil {
360 return olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
361 }
362 if indications == nil {
363 return olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
364 }
365 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000366 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530367 if err != nil {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400368 if dh.adminState == "deleted" {
369 log.Debug("Device deleted stoping the read indication thread")
370 break
371 }
372 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530373 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400374 // Reset backoff if we have a successful receive
375 indicationBackoff.Reset()
376 dh.lockDevice.RLock()
377 adminState := dh.adminState
378 dh.lockDevice.RUnlock()
379 // When OLT is admin down, ignore all indications.
380 if adminState == "down" && !isIndicationAllowedDuringOltAdminDown(indication) {
381 log.Debugw("olt is admin down, ignore indication", log.Fields{"indication": indication})
382 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400383 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400384 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700385 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700386 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400387}
388
389// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
390func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
391 switch indication.Data.(type) {
392 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
393 return true
394
395 default:
396 return false
397 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700398}
399
David K. Bainbridge794735f2020-02-11 21:01:37 -0800400func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000401 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000402 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530403 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700404 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530405 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700406 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000407 // Send or clear Alarm
David K. Bainbridge794735f2020-02-11 21:01:37 -0800408 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530409 return olterrors.NewErrAdapter("failed-indication", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800410 "device_id": dh.deviceID,
411 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000412 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800413 }
414 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700415}
416
David K. Bainbridge794735f2020-02-11 21:01:37 -0800417// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530418func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400419 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700420 switch indication.Data.(type) {
421 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800422 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530423 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800424 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700425 case *oop.Indication_IntfInd:
426 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800427 go func() {
428 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530429 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800430 }
431 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700432 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
433 case *oop.Indication_IntfOperInd:
434 intfOperInd := indication.GetIntfOperInd()
435 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800436 go func() {
437 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530438 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800439 }
440 }()
npujarec5762e2020-01-01 14:08:48 +0530441 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700442 } else if intfOperInd.GetType() == "pon" {
443 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
444 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800445 go func() {
446 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530447 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800448 }
449 }()
kesavand39e0aa32020-01-28 20:58:50 -0500450 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700451 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700452 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
453 case *oop.Indication_OnuDiscInd:
454 onuDiscInd := indication.GetOnuDiscInd()
455 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700456 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800457 go func() {
458 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530459 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800460 }
461 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700462 case *oop.Indication_OnuInd:
463 onuInd := indication.GetOnuInd()
464 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800465 go func() {
466 if err := dh.onuIndication(onuInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530467 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800468 }
469 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700470 case *oop.Indication_OmciInd:
471 omciInd := indication.GetOmciInd()
lcuie24ef182019-04-29 22:58:36 -0700472 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 -0800473 go func() {
474 if err := dh.omciIndication(omciInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530475 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800476 }
477 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700478 case *oop.Indication_PktInd:
479 pktInd := indication.GetPktInd()
480 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 go func() {
482 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530483 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800484 }
485 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700486 case *oop.Indication_PortStats:
487 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530488 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700489 case *oop.Indication_FlowStats:
490 flowStats := indication.GetFlowStats()
491 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
492 case *oop.Indication_AlarmInd:
493 alarmInd := indication.GetAlarmInd()
494 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530495 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700496 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530497}
498
499// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530500func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400501 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530502 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400503 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000504 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400505 }
506 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530507}
508
509// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530510func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700511 dh.lockDevice.Lock()
512 defer dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400513 log.Debug("do-state-down-start")
514
npujarec5762e2020-01-01 14:08:48 +0530515 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400516 if err != nil || device == nil {
517 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000518 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400519 }
520
521 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400522
523 //Update the device oper state and connection status
524 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400525 dh.device = cloned
526
David K. Bainbridge794735f2020-02-11 21:01:37 -0800527 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000528 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400529 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400530
531 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530532 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400533 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000534 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400535 }
536 for _, onuDevice := range onuDevices.Items {
537
538 // Update onu state as down in onu adapter
539 onuInd := oop.OnuIndication{}
540 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800541 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700542 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800543 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530544 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800545 "source": "openolt",
546 "onu-indicator": onuInd,
547 "device-type": onuDevice.Type,
548 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700549 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700550 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400551 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700552 /* Discovered ONUs entries need to be cleared , since after OLT
553 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530554 dh.discOnus = sync.Map{}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800555 log.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700556 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530557}
558
559// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530560func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400561 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800562 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530563 return olterrors.NewErrCommunication("dial-failure", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800564 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000565 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400566 }
567 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530568}
569
570// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530571func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400572 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530573 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400574 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530575}
576
577// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530578func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400579 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400580
581 // Case where OLT is disabled and then rebooted.
582 if dh.adminState == "down" {
583 log.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530584 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400585 if err != nil || device == nil {
586 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530587 olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400588 }
589
590 cloned := proto.Clone(device).(*voltha.Device)
591 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
592 cloned.OperStatus = voltha.OperStatus_UNKNOWN
593 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530594 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530595 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400596 }
597
Chaitrashree G S44124192019-08-07 20:21:36 -0400598 // 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 +0530599 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400600 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530601 olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400602 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400603 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
604 // all the modules initialized and ready to handle incoming ONUs.
605
606 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
607 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
608 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400609
610 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800611 go func() {
612 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530613 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800614 }
615 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400616 return nil
617 }
618
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700619 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400620 if err != nil || device == nil {
621 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000622 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400623 }
kesavand39e0aa32020-01-28 20:58:50 -0500624 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500625 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000626 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400627 }
628
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400629 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
630 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400631 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530632
cuilin20187b2a8c32019-03-26 19:52:28 -0700633 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800634 go func() {
635 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530636 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800637 }
638 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700639 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530640}
641
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400642func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
643 deviceInfo, err := dh.populateDeviceInfo()
644
645 if err != nil {
646 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
647 }
648 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
649 // Instantiate resource manager
650 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
651 return olterrors.ErrResourceManagerInstantiating
652 }
653
654 // Instantiate flow manager
655 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
656 return olterrors.ErrResourceManagerInstantiating
657
658 }
659 /* TODO: Instantiate Alarm , stats , BW managers */
660 /* Instantiating Event Manager to handle Alarms and KPIs */
661 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
662
663 // Stats config for new device
664 dh.portStats = NewOpenOltStatsMgr(dh)
665
666 return nil
667
668}
669
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400670func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
671 var err error
672 var deviceInfo *oop.DeviceInfo
673
674 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
675
676 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000677 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400678 }
679 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000680 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400681 }
682
683 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
684 dh.device.Root = true
685 dh.device.Vendor = deviceInfo.Vendor
686 dh.device.Model = deviceInfo.Model
687 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
688 dh.device.HardwareVersion = deviceInfo.HardwareVersion
689 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
690
691 if deviceInfo.DeviceId == "" {
692 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
693 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
694 genmac, err := generateMacFromHost(host)
695 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000696 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400697 }
698 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
699 dh.device.MacAddress = genmac
700 } else {
701 dh.device.MacAddress = deviceInfo.DeviceId
702 }
703
704 // Synchronous call to update device - this method is run in its own go routine
705 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000706 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400707 }
708
709 return deviceInfo, nil
710}
711
Naga Manjunath7615e552019-10-11 22:35:47 +0530712func startCollector(dh *DeviceHandler) {
713 // Initial delay for OLT initialization
714 time.Sleep(1 * time.Minute)
715 log.Debugf("Starting-Collector")
716 context := make(map[string]string)
717 for {
718 select {
719 case <-dh.stopCollector:
720 log.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
721 return
722 default:
723 freq := dh.metrics.ToPmConfigs().DefaultFreq
724 time.Sleep(time.Duration(freq) * time.Second)
725 context["oltid"] = dh.deviceID
726 context["devicetype"] = dh.deviceType
727 // NNI Stats
728 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
729 log.Debugf("Collect-NNI-Metrics %v", cmnni)
730 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
731 log.Debugf("Publish-NNI-Metrics")
732 // PON Stats
733 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
Chaitrashree G Sef088112020-02-03 21:39:27 -0500734 for i := uint32(0); i < NumPonPORTS; i++ {
735 if val, ok := dh.activePorts.Load(i); ok && val == true {
736 cmpon := dh.portStats.collectPONMetrics(i)
737 log.Debugf("Collect-PON-Metrics %v", cmpon)
Naga Manjunath7615e552019-10-11 22:35:47 +0530738
Chaitrashree G Sef088112020-02-03 21:39:27 -0500739 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
740 log.Debugf("Publish-PON-Metrics")
741 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530742 }
743 }
744 }
745}
746
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700747//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530748func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400749 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700750 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530751 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530752
753 // Now, set the initial PM configuration for that device
754 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530755 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530756 }
757
758 go startCollector(dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400759 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530760}
761
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700762//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530763func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700764 return &ic.SwitchCapability{
765 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530766 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700767 HwDesc: "open_pon",
768 SwDesc: "open_pon",
769 SerialNum: dh.device.SerialNumber,
770 },
771 SwitchFeatures: &of.OfpSwitchFeatures{
772 NBuffers: 256,
773 NTables: 2,
774 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
775 of.OfpCapabilities_OFPC_TABLE_STATS |
776 of.OfpCapabilities_OFPC_PORT_STATS |
777 of.OfpCapabilities_OFPC_GROUP_STATS),
778 },
779 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530780}
781
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700782//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530783func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700784 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700785 return &ic.PortCapability{
786 Port: &voltha.LogicalPort{
787 OfpPort: &of.OfpPort{
788 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
789 Config: 0,
790 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700791 Curr: capacity,
792 Advertised: capacity,
793 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700794 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
795 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
796 },
797 DeviceId: dh.device.Id,
798 DevicePortNo: uint32(portNo),
799 },
800 }, nil
801}
802
David K. Bainbridge794735f2020-02-11 21:01:37 -0800803func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700804 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700805 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700806 var deviceID string
807 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700808
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700809 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530810
811 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
812
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700813 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
814 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700815 kwargs := make(map[string]interface{})
816 kwargs["onu_id"] = omciInd.OnuId
817 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700818
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700819 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
820 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530821 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800822 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000823 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700824 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700825 deviceType = onuDevice.Type
826 deviceID = onuDevice.Id
827 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
828 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530829 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700830 } else {
831 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700832 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530833 deviceType = onuInCache.(*OnuDevice).deviceType
834 deviceID = onuInCache.(*OnuDevice).deviceID
835 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700836 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700837
838 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800839 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700840 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800841 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530842 return olterrors.NewErrCommunication("omci-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800843 "source": dh.deviceType,
844 "destination": deviceType,
845 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000846 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700847 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800848 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530849}
850
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700851//ProcessInterAdapterMessage sends the proxied messages to the target device
852// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
853// is meant, and then send the unmarshalled omci message to this onu
854func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
855 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700856 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700857 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700858 fromTopic := msg.Header.FromTopic
859 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700860 toDeviceID := msg.Header.ToDeviceId
861 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700862
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700863 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700864
865 msgBody := msg.GetBody()
866
867 omciMsg := &ic.InterAdapterOmciMessage{}
868 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000869 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700870 }
871
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700872 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700873 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
874 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530875 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800876 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000877 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700878 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700879 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 -0800880 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530881 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800882 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000883 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800884 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700885 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700886 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 -0800887 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530888 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800889 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000890 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800891 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700892 }
893
894 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000895 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700896 }
897 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530898}
899
David K. Bainbridge794735f2020-02-11 21:01:37 -0800900func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700901 var intfID uint32
902 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000903 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700904 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700905 intfID = onuDevice.ProxyAddress.GetChannelId()
906 onuID = onuDevice.ProxyAddress.GetOnuId()
907 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700908 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700909 intfID = omciMsg.GetProxyAddress().GetChannelId()
910 onuID = omciMsg.GetProxyAddress().GetOnuId()
911 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700912 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700913 if connectStatus != voltha.ConnectStatus_REACHABLE {
914 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800915
Thomas Lee S94109f12020-03-03 16:39:29 +0530916 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800917 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000918 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700919 }
920
lcuie24ef182019-04-29 22:58:36 -0700921 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
922 isHexString := false
923 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
924 if decodeerr == nil {
925 isHexString = true
926 }
927
928 // 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.
929 var omciMessage *oop.OmciMsg
930 if isHexString {
931 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
932 } else {
933 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
934 hex.Encode(hexPkt, omciMsg.Message)
935 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
936 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700937
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700938 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
939 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530940 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800941 "interface-id": intfID,
942 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000943 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700944 }
lcuie24ef182019-04-29 22:58:36 -0700945 log.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800946 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700947}
948
David K. Bainbridge794735f2020-02-11 21:01:37 -0800949func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700950 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
npujarec5762e2020-01-01 14:08:48 +0530951 dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700952 // TODO: need resource manager
953 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700954 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +0530955 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400956 st, _ := status.FromError(err)
957 if st.Code() == codes.AlreadyExists {
958 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
959 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000960 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400961 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700962 } else {
963 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
964 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800965 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700966}
967
David K. Bainbridge794735f2020-02-11 21:01:37 -0800968func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800969
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700970 channelID := onuDiscInd.GetIntfId()
971 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400972
Matteo Scandolo945e4012019-12-12 14:16:11 -0800973 log.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530974
cuilin20187b2a8c32019-03-26 19:52:28 -0700975 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400976 if sn != "" {
977 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400978 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000979 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400980 }
981
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530982 var alarmInd oop.OnuAlarmIndication
983 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +0000984 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530985
986 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
987 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
988 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
989 OnuLosRaise event sent for it */
990 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
991 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
992 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
993 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
994 "previousIntfId": onuInCache.(*OnuDevice).intfID,
995 "currentIntfId": onuDiscInd.GetIntfId()})
996 // TODO:: Should we need to ignore raising OnuLosClear event
997 // when onu connected to different PON?
998 }
999 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1000 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1001 alarmInd.LosStatus = statusCheckOff
1002 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1003 }
1004 return true
1005 })
1006
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001007 log.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001008 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001009 }
1010
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001011 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001012
1013 // check the ONU is already know to the OLT
1014 // NOTE the second time the ONU is discovered this should return a device
1015 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1016
1017 if err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001018 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 -08001019 if e, ok := status.FromError(err); ok {
1020 log.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
1021 switch e.Code() {
1022 case codes.Internal:
1023 // this probably means NOT FOUND, so just create a new device
1024 onuDevice = nil
1025 case codes.DeadlineExceeded:
1026 // if the call times out, cleanup and exit
1027 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001028 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001029 }
1030 }
1031 }
1032
1033 if onuDevice == nil {
1034 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
1035 log.Infow("creating-new-onu", log.Fields{"sn": sn})
1036 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001037 ponintfid := onuDiscInd.GetIntfId()
1038 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301039 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001040 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001041
Matteo Scandolo945e4012019-12-12 14:16:11 -08001042 log.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
1043
1044 if err != nil {
1045 // if we can't create an ID in resource manager,
1046 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001047 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001048 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001049 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001050 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001051 }
1052
1053 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1054 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001055 dh.discOnus.Delete(sn)
1056 dh.resourceMgr.FreeonuID(ctx, ponintfid, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301057 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001058 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001059 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001060 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -05001061 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Matteo Scandolo945e4012019-12-12 14:16:11 -08001062 log.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001063 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001064
1065 // we can now use the existing ONU Id
1066 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001067 //Insert the ONU into cache to use in OnuIndication.
1068 //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 -08001069 log.Debugw("onu-discovery-indication-key-create", log.Fields{"onuID": onuID,
1070 "intfId": onuDiscInd.GetIntfId(), "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001071 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001072
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301073 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301074 dh.onus.Store(onuKey, onuDev)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001075 log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001076
David K. Bainbridge794735f2020-02-11 21:01:37 -08001077 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301078 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001079 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001080 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001081 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001082 log.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001083 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301084 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001085 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001086 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001087 }
1088 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001089}
1090
David K. Bainbridge794735f2020-02-11 21:01:37 -08001091func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001092 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1093
1094 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001095 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001096 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001097 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001098 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -07001099 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
1100 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001101 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301102
David K. Bainbridge794735f2020-02-11 21:01:37 -08001103 errFields := log.Fields{"device-id": dh.device.Id}
1104
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301105 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1106
Mahir Gunyele77977b2019-06-27 05:36:22 -07001107 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1108 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001109 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1110 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001111 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001112 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1113 if serialNumber != "" {
1114 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001115 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001116 } else {
1117 kwargs["onu_id"] = onuInd.OnuId
1118 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001119 errFields["onu-id"] = onuInd.OnuId
1120 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001121 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001122 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001123 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001124
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001126 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001127 }
1128
David K. Bainbridge794735f2020-02-11 21:01:37 -08001129 if onuDevice.ParentPortNo != ponPort {
1130 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
1131 "previousIntfId": onuDevice.ParentPortNo,
1132 "currentIntfId": ponPort})
1133 }
1134
1135 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
1136 log.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
1137 "expected_onu_id": onuDevice.ProxyAddress.OnuId,
1138 "received_onu_id": onuInd.OnuId})
1139 }
1140 if !foundInCache {
1141 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1142
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301143 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001144
1145 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001146 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001147 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001148 }
1149 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001150}
1151
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001152func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301153 ctx := context.TODO()
Matt Jeanneret53539512019-07-20 14:47:02 -04001154 log.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001155 if onuInd.AdminState == "down" {
1156 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1157 if onuInd.OperState != "down" {
1158 log.Warnw("ONU-admin-state-down", log.Fields{"operState": onuInd.OperState})
1159 onuInd.OperState = "down"
1160 }
1161 }
1162
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 switch onuInd.OperState {
1164 case "down":
Matt Jeanneret53539512019-07-20 14:47:02 -04001165 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 -07001166 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301167 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001168 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1169 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301170 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001171 "onu-indicator": onuInd,
1172 "source": "openolt",
1173 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001174 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001175 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001176 case "up":
Matt Jeanneret53539512019-07-20 14:47:02 -04001177 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
1178 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301179 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001180 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1181 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301182 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001183 "onu-indicator": onuInd,
1184 "source": "openolt",
1185 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001186 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001187 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001188 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001189 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001190 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001191 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001192}
1193
cuilin20187b2a8c32019-03-26 19:52:28 -07001194func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1195 if serialNum != nil {
1196 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001197 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001198 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001199}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001200func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1201 decodedStr, err := hex.DecodeString(serialNum[4:])
1202 if err != nil {
1203 return nil, err
1204 }
1205 return &oop.SerialNumber{
1206 VendorId: []byte(serialNum[:4]),
1207 VendorSpecific: []byte(decodedStr),
1208 }, nil
1209}
cuilin20187b2a8c32019-03-26 19:52:28 -07001210
1211func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1212 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001213 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001214 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1215 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1216 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1217 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1218 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1219 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1220 return tmp
1221}
1222
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001223//UpdateFlowsBulk upates the bulk flow
1224func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301225 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001226}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001227
1228//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001229func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001230 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001231 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001232 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001233 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001234 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001235 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001236 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001237 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001238 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001239 }
1240 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001241 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301242}
1243
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001244// SendPacketInToCore sends packet-in to core
1245// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1246// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001247func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001248 log.Debugw("send-packet-in-to-core", log.Fields{
1249 "port": logicalPort,
1250 "packet": hex.EncodeToString(packetPayload),
1251 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001252 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301253 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001254 "source": "adapter",
1255 "destination": "core",
1256 "device-id": dh.device.Id,
1257 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001258 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001259 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001260 log.Debugw("Sent packet-in to core successfully", log.Fields{
1261 "packet": hex.EncodeToString(packetPayload),
1262 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001264}
1265
A R Karthick1f85b802019-10-11 05:06:05 +00001266// AddUniPortToOnu adds the uni port to the onu device
1267func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1268 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301269
1270 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001271 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301272 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1273 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001274 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1275 }
1276 }
1277}
1278
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001279//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301280func (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 -04001281 log.Debugw("Received-incremental-flowupdate-in-device-handler", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001282
1283 var errorsList []error
1284
Girish Gowdru0c588b22019-04-23 23:24:56 -04001285 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001286 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001287 dh.incrementActiveFlowRemoveCount(flow)
1288
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001289 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001290 err := dh.flowMgr.RemoveFlow(ctx, flow)
1291 if err != nil {
1292 errorsList = append(errorsList, err)
1293 }
1294
1295 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001296 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301297
1298 for _, flow := range flows.ToAdd.Items {
1299 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001300 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1301 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001302 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1303 if err != nil {
1304 errorsList = append(errorsList, err)
1305 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301306 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001307 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001308 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001309 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001310 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001311 // dh.flowMgr.RemoveFlow(flow)
1312 }
1313 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001314
Girish Gowdracefae192020-03-19 18:14:10 -07001315 // Whether we need to synchronize multicast group adds and modifies like flow add and delete needs to be investigated
Esin Karamanccb714b2019-11-29 15:02:06 +00001316 if groups != nil {
1317 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001318 err := dh.flowMgr.AddGroup(ctx, group)
1319 if err != nil {
1320 errorsList = append(errorsList, err)
1321 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001322 }
1323 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001324 err := dh.flowMgr.ModifyGroup(ctx, group)
1325 if err != nil {
1326 errorsList = append(errorsList, err)
1327 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001328 }
1329 if len(groups.ToRemove.Items) != 0 {
1330 log.Debug("Group delete operation is not supported for now")
1331 }
1332 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001333 if len(errorsList) > 0 {
1334 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1335 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001336 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001337 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301338}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001339
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001340//DisableDevice disables the given device
1341//It marks the following for the given device:
1342//Device-Handler Admin-State : down
1343//Device Port-State: UNKNOWN
1344//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001345func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001346 /* On device disable ,admin state update has to be done prior sending request to agent since
1347 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001348 dh.lockDevice.Lock()
1349 dh.adminState = "down"
1350 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001351 if dh.Client != nil {
1352 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1353 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001354 dh.lockDevice.Lock()
1355 dh.adminState = "up"
1356 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001357 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001358 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001359 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001360 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001361 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001362 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001363 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301364
1365 dh.discOnus = sync.Map{}
1366 dh.onus = sync.Map{}
1367
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301368 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001369 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001370 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1371 for _, port := range cloned.Ports {
1372 if port.GetType() == voltha.Port_PON_OLT {
1373 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1374 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001375 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001376 }
1377 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001378 }
1379
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001380 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001381 return nil
1382}
1383
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301384func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001385
1386 // Update onu state as unreachable in onu adapter
1387 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301388 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001389 //get the child device for the parent device
1390 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1391 if err != nil {
1392 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1393 }
1394 if onuDevices != nil {
1395 for _, onuDevice := range onuDevices.Items {
1396 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1397 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1398 if err != nil {
1399 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1400 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1401 }
1402
1403 }
1404 }
1405
1406}
1407
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001408//ReenableDevice re-enables the olt device after disable
1409//It marks the following for the given device:
1410//Device-Handler Admin-State : up
1411//Device Port-State: ACTIVE
1412//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001413func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001414 dh.lockDevice.Lock()
1415 dh.adminState = "up"
1416 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301417
1418 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1419 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301420 dh.lockDevice.Lock()
1421 dh.adminState = "down"
1422 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001423 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301424 }
1425 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001426 log.Debug("olt-reenabled")
1427
1428 cloned := proto.Clone(device).(*voltha.Device)
1429 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001430
kdarapu1afeceb2020-02-12 01:38:09 -05001431 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001432 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001433 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001434 //Update the device oper status as ACTIVE
1435 cloned.OperStatus = voltha.OperStatus_ACTIVE
1436 dh.device = cloned
1437
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001438 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301439 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001440 "device-id": device.Id,
1441 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001442 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001443 }
kesavand39e0aa32020-01-28 20:58:50 -05001444
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001446
1447 return nil
1448}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001449
npujarec5762e2020-01-01 14:08:48 +05301450func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001451 var uniID uint32
1452 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301453 for _, port := range onu.UniPorts {
1454 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001455 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1456 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301457 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301458 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001459 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301460 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301461 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001462 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301463 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001464 }
npujarec5762e2020-01-01 14:08:48 +05301465 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001466 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301467 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301468 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001469 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301470 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301471 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301472 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001473 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301474 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1475 }
npujarec5762e2020-01-01 14:08:48 +05301476 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1477 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301478 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1479 }
1480 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301481 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301482 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 +00001483 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001484 }
1485 return nil
1486}
1487
npujarec5762e2020-01-01 14:08:48 +05301488func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001489 nniUniID := -1
1490 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301491
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001492 if dh.resourceMgr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001493 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.deviceID}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001494 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001495 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301496 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301497 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001498 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001499 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301500 log.Debugw("NNI are ", log.Fields{"nni": nni})
1501 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301502 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301503 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1504 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301505 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301506 }
npujarec5762e2020-01-01 14:08:48 +05301507 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001508 }
npujarec5762e2020-01-01 14:08:48 +05301509 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001510 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301511 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001512 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001513}
1514
1515// 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 +05301516func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001517 log.Debug("Function entry delete device")
1518 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001519 if dh.adminState == "deleted" {
1520 dh.lockDevice.Unlock()
1521 return nil
1522 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001523 dh.adminState = "deleted"
1524 dh.lockDevice.Unlock()
1525 /* Clear the KV store data associated with the all the UNI ports
1526 This clears up flow data and also resource map data for various
1527 other pon resources like alloc_id and gemport_id
1528 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001529 go dh.cleanupDeviceResources(ctx)
1530 log.Debug("Removed-device-from-Resource-manager-KV-store")
1531 // Stop the Stats collector
1532 dh.stopCollector <- true
1533 // stop the heartbeat check routine
1534 dh.stopHeartbeatCheck <- true
1535 //Reset the state
1536 if dh.Client != nil {
1537 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
1538 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
1539 }
1540 }
1541 cloned := proto.Clone(device).(*voltha.Device)
1542 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1543 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1544 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1545 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1546 "device-id": device.Id,
1547 "connect-status": cloned.ConnectStatus,
1548 "oper-status": cloned.OperStatus}, err).Log()
1549 }
1550 return nil
1551}
1552func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001553 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301554 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1555 var ponPort uint32
1556 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1557 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301558 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301559 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301560 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001561 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001562 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301563 }
1564 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301565 onuID := make([]uint32, 1)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301566 log.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301567 if err = dh.clearUNIData(ctx, &onu); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301568 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1569 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301570 // Clear flowids for gem cache.
1571 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301572 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301573 }
1574 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301575 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301576 }
npujarec5762e2020-01-01 14:08:48 +05301577 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301578 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301579 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301580 if err != nil {
1581 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001582 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001583 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001584 /* Clear the flows from KV store associated with NNI port.
1585 There are mostly trap rules from NNI port (like LLDP)
1586 */
npujarec5762e2020-01-01 14:08:48 +05301587 if err := dh.clearNNIData(ctx); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301588 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001589 }
A R Karthick1f85b802019-10-11 05:06:05 +00001590
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001591 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301592 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001593 }
A R Karthick1f85b802019-10-11 05:06:05 +00001594
Devmalya Paul495b94a2019-08-27 19:42:00 -04001595 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301596 dh.onus.Range(func(key interface{}, value interface{}) bool {
1597 dh.onus.Delete(key)
1598 return true
1599 })
1600
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001601 /*Delete discovered ONU map for the device*/
1602 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1603 dh.discOnus.Delete(key)
1604 return true
1605 })
1606
Devmalya Paul495b94a2019-08-27 19:42:00 -04001607 return nil
1608}
1609
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001610//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001611func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1612 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001613 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001614 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001615 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001616 return nil
1617}
1618
David K. Bainbridge794735f2020-02-11 21:01:37 -08001619func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001620 log.Debugw("Received packet-in", log.Fields{
1621 "packet-indication": *packetIn,
1622 "packet": hex.EncodeToString(packetIn.Pkt),
1623 })
npujarec5762e2020-01-01 14:08:48 +05301624 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001625 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001626 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001627 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001628 log.Debugw("sending packet-in to core", log.Fields{
1629 "logicalPortNum": logicalPortNum,
1630 "packet": hex.EncodeToString(packetIn.Pkt),
1631 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001632 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301633 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001634 "destination": "core",
1635 "source": dh.deviceType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001636 "packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001637 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001638 log.Debugw("Success sending packet-in to core!", log.Fields{
1639 "packet": hex.EncodeToString(packetIn.Pkt),
1640 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001641 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001642}
1643
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001644// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301645func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001646 log.Debugw("incoming-packet-out", log.Fields{
1647 "deviceID": dh.deviceID,
1648 "egress_port_no": egressPortNo,
1649 "pkt-length": len(packet.Data),
1650 "packet": hex.EncodeToString(packet.Data),
1651 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001652
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001653 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001654 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001655 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1656 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301657 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1658 // Do not packet-out lldp packets on uni port.
1659 // ONOS has no clue about uni/nni ports, it just packets out on all
1660 // available ports on the Logical Switch. It should not be interested
1661 // in the UNI links.
1662 log.Debug("dropping-lldp-packet-out-on-uni")
1663 return nil
1664 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001665 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1666 if innerEthType == 0x8100 {
1667 // q-in-q 802.1ad or 802.1q double tagged packet.
1668 // slice out the outer tag.
1669 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1670 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001671 }
1672 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001673 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1674 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001675 uniID := UniIDFromPortNum(uint32(egressPortNo))
1676
npujarec5762e2020-01-01 14:08:48 +05301677 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001678 if err != nil {
1679 // In this case the openolt agent will receive the gemPortID as 0.
1680 // The agent tries to retrieve the gemPortID in this case.
1681 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001682 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1683 "packet": hex.EncodeToString(packet.Data),
1684 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001685 }
1686
1687 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001688
Matteo Scandolo6056e822019-11-13 14:05:29 -08001689 log.Debugw("sending-packet-to-onu", log.Fields{
1690 "egress_port_no": egressPortNo,
1691 "IntfId": intfID,
1692 "onuID": onuID,
1693 "uniID": uniID,
1694 "gemPortID": gemPortID,
1695 "packet": hex.EncodeToString(packet.Data),
1696 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001697
npujarec5762e2020-01-01 14:08:48 +05301698 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301699 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001700 "source": "adapter",
1701 "destination": "onu",
1702 "egress-port-number": egressPortNo,
1703 "interface-id": intfID,
1704 "oni-id": onuID,
1705 "uni-id": uniID,
1706 "gem-port-id": gemPortID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001707 "packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001708 }
1709 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001710 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1711 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001712 return olterrors.NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001713 }
1714 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001715
Matteo Scandolo6056e822019-11-13 14:05:29 -08001716 log.Debugw("sending-packet-to-nni", log.Fields{
1717 "uplink_pkt": uplinkPkt,
1718 "packet": hex.EncodeToString(packet.Data),
1719 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001720
npujarec5762e2020-01-01 14:08:48 +05301721 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001722 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001723 }
1724 } else {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001725 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1726 "egress_port_no": egressPortNo,
1727 "egressPortType": egressPortType,
1728 "packet": hex.EncodeToString(packet.Data),
1729 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001730 }
1731 return nil
1732}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001733
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001734func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1735 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001736}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301737
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001738func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301739 // start the heartbeat check towards the OLT.
1740 var timerCheck *time.Timer
1741
1742 for {
1743 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1744 select {
1745 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001746 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1747 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301748 log.Error("Hearbeat failed")
1749 if timerCheck == nil {
1750 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001751 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301752 }
1753 } else {
1754 if timerCheck != nil {
1755 if timerCheck.Stop() {
1756 log.Debug("We got hearbeat within the timeout")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301757 }
1758 timerCheck = nil
1759 }
1760 log.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
1761 }
1762 cancel()
1763 case <-dh.stopHeartbeatCheck:
1764 log.Debug("Stopping heart beat check")
1765 return
1766 }
1767 }
1768}
1769
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001770func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1771 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1772 if err != nil || device == nil {
1773 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1774 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301775
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001776 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1777 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1778 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1779 }
1780 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1781 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1782 }
1783 go dh.cleanupDeviceResources(ctx)
1784
1785 dh.stopIndications <- true
1786 dh.transitionMap.Handle(ctx, DeviceInit)
1787
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301788 }
1789}
kesavand39e0aa32020-01-28 20:58:50 -05001790
1791// EnablePort to enable Pon interface
1792func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
1793 log.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001794 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001795}
1796
1797// DisablePort to disable pon interface
1798func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
1799 log.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001800 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001801}
1802
kdarapu1afeceb2020-02-12 01:38:09 -05001803//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1804func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301805 ctx := context.Background()
kdarapu1afeceb2020-02-12 01:38:09 -05001806 log.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort})
kesavand39e0aa32020-01-28 20:58:50 -05001807 if port.GetType() == voltha.Port_ETHERNET_NNI {
1808 // Bug is opened for VOL-2505 to support NNI disable feature.
1809 log.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
1810 log.Fields{"Device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301811 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001812 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001813 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001814 }
1815 // fetch interfaceid from PortNo
1816 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1817 ponIntf := &oop.Interface{IntfId: ponID}
1818 var operStatus voltha.OperStatus_Types
1819 if enablePort {
1820 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301821 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001822
1823 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301824 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001825 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001826 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001827 }
1828 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001829 dh.activePorts.Store(ponID, true)
kesavand39e0aa32020-01-28 20:58:50 -05001830 log.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1831 } else {
1832 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301833 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001834 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301835 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001836 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001837 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001838 }
1839 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001840 dh.activePorts.Store(ponID, false)
kesavand39e0aa32020-01-28 20:58:50 -05001841 log.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1842 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001843 if err := dh.coreProxy.PortStateUpdate(ctx, dh.deviceID, voltha.Port_PON_OLT, port.PortNo, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301844 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001845 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001846 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001847 }
1848 return nil
1849}
1850
kdarapu1afeceb2020-02-12 01:38:09 -05001851//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1852func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001853 cloned := proto.Clone(device).(*voltha.Device)
1854 // Disable the port and update the oper_port_status to core
1855 // if the Admin state of the port is disabled on reboot and re-enable device.
1856 for _, port := range cloned.Ports {
1857 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001858 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301859 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001860 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001861 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001862 }
1863 }
1864 }
1865 return nil
1866}
1867
1868//populateActivePorts to populate activePorts map
1869func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
1870 log.Info("populateActiveports", log.Fields{"Device": device})
1871 for _, port := range device.Ports {
1872 if port.Type == voltha.Port_ETHERNET_NNI {
1873 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001874 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001875 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001876 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001877 }
1878 }
1879 if port.Type == voltha.Port_PON_OLT {
1880 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001881 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001882 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001883 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001884 }
1885 }
1886 }
1887}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001888
1889// ChildDeviceLost deletes ONU and clears pon resources related to it.
1890func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
1891 log.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
1892 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1893 onuKey := dh.formOnuKey(IntfID, onuID)
1894 onuDevice, ok := dh.onus.Load(onuKey)
1895 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301896 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001897 log.Fields{
1898 "device-id": dh.deviceID,
1899 "onu-id": onuID,
1900 "interface-id": IntfID}, nil).Log()
1901 }
1902 var sn *oop.SerialNumber
1903 var err error
1904 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301905 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001906 log.Fields{
1907 "devicer-id": dh.deviceID,
1908 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
1909 }
1910 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
1911 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301912 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001913 "device-id": dh.deviceID,
1914 "onu-id": onuID}, err).Log()
1915 }
1916 //clear PON resources associated with ONU
1917 var onuGemData []rsrcMgr.OnuGemInfo
1918 if err := dh.resourceMgr.ResourceMgrs[IntfID].GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001919 log.Warnw("Failed-to-get-onu-info-for-pon-port ", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001920 "device-id": dh.deviceID,
1921 "interface-id": IntfID,
1922 "error": err})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001923 } else {
1924 for i, onu := range onuGemData {
1925 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
1926 log.Debugw("onu-data ", log.Fields{"onu": onu})
1927 if err := dh.clearUNIData(ctx, &onu); err != nil {
1928 log.Warnw("Failed-to-clear-uni-data-for-onu", log.Fields{
1929 "device-id": dh.deviceID,
1930 "onu-device": onu,
1931 "error": err})
1932 }
1933 // Clear flowids for gem cache.
1934 for _, gem := range onu.GemPorts {
1935 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
1936 }
1937 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
1938 dh.resourceMgr.UpdateOnuGemInfo(ctx, IntfID, onuGemData)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001939
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001940 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
1941 break
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001942 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001943 }
1944 }
1945 dh.onus.Delete(onuKey)
1946 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
1947 return nil
1948}
Girish Gowdracefae192020-03-19 18:14:10 -07001949
1950func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
1951 for _, field := range flows.GetOfbFields(flow) {
1952 if field.Type == flows.IN_PORT {
1953 return field.GetPort()
1954 }
1955 }
1956 return InvalidPort
1957}
1958
1959func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
1960 for _, action := range flows.GetActions(flow) {
1961 if action.Type == flows.OUTPUT {
1962 if out := action.GetOutput(); out != nil {
1963 return out.GetPort()
1964 }
1965 }
1966 }
1967 return InvalidPort
1968}
1969
1970func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
1971 inPort, outPort := getPorts(flow)
1972 log.Debugw("increment flow remove count for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
1973 if inPort != InvalidPort && outPort != InvalidPort {
1974 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
1975 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
1976 log.Debugw("increment flow remove count for subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1977
1978 dh.lockDevice.Lock()
1979 defer dh.lockDevice.Unlock()
1980 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
1981 if !ok {
1982 flowRemoveData = pendingFlowRemoveData{
1983 pendingFlowRemoveCount: 0,
1984 allFlowsRemoved: make(chan struct{}),
1985 }
1986 }
1987 flowRemoveData.pendingFlowRemoveCount++
1988 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
1989
1990 log.Debugw("current flow remove count after increment",
1991 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
1992 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
1993 }
1994}
1995
1996func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
1997 inPort, outPort := getPorts(flow)
1998 log.Debugw("decrement flow remove count for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
1999 if inPort != InvalidPort && outPort != InvalidPort {
2000 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2001 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
2002 log.Debugw("decrement flow remove count for subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
2003
2004 dh.lockDevice.Lock()
2005 defer dh.lockDevice.Unlock()
2006 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2007 log.Fatalf("flow remove key not found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
2008 } else {
2009 if val.pendingFlowRemoveCount > 0 {
2010 val.pendingFlowRemoveCount--
2011 }
2012 log.Debugw("current flow remove count after decrement",
2013 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2014 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2015 // If all flow removes have finished, then close the channel to signal the receiver
2016 // to go ahead with flow adds.
2017 if val.pendingFlowRemoveCount == 0 {
2018 close(val.allFlowsRemoved)
2019 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2020 return
2021 }
2022 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2023 }
2024 }
2025}
2026
2027func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2028 var flowRemoveData pendingFlowRemoveData
2029 var ok bool
2030 inPort, outPort := getPorts(flow)
2031 log.Debugw("wait for flow remove to finish for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
2032 if inPort != InvalidPort && outPort != InvalidPort {
2033 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2034 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
2035 log.Debugw("wait for flow remove to finish for subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
2036
2037 dh.lockDevice.RLock()
2038 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2039 log.Debugw("no pending flow to remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
2040 dh.lockDevice.RUnlock()
2041 return
2042 }
2043 dh.lockDevice.RUnlock()
2044
2045 // Wait for all flow removes to finish first
2046 <-flowRemoveData.allFlowsRemoved
2047
2048 log.Debugw("all flows cleared, handling flow add now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
2049 }
2050}
2051
2052func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2053 inPort := getInPortFromFlow(flow)
2054 outPort := getOutPortFromFlow(flow)
2055
2056 if inPort == InvalidPort || outPort == InvalidPort {
2057 return inPort, outPort
2058 }
2059
2060 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2061 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2062 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2063 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2064 return uniPort, outPort
2065 }
2066 }
2067 } else {
2068 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2069 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2070 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2071 return inPort, uniPort
2072 }
2073 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2074 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2075 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2076 return uniPort, outPort
2077 }
2078 }
2079 }
2080
2081 return InvalidPort, InvalidPort
2082}